mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 09:17:49 +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/cenkalti/backoff v2.1.1+incompatible // indirect
|
||||||
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e // indirect
|
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e // indirect
|
||||||
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e
|
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e
|
||||||
github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0
|
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect
|
|
||||||
github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20 // indirect
|
github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20 // indirect
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190315220205-a8ed825ac853 // indirect
|
github.com/denisenkom/go-mssqldb v0.0.0-20190315220205-a8ed825ac853 // indirect
|
||||||
github.com/docker/cli v1.14.0-0.20190523191156-ab688a9a79a1
|
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/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.4.1 // 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/flock v0.7.0
|
||||||
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
||||||
github.com/gogo/protobuf v1.2.1 // 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/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
|
||||||
github.com/hashicorp/go-version v1.1.0 // indirect
|
github.com/hashicorp/go-version v1.1.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0
|
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/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/jinzhu/gorm v1.9.2 // indirect
|
github.com/jinzhu/gorm v1.9.2 // indirect
|
||||||
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // 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/mattn/go-sqlite3 v1.10.0 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||||
github.com/miekg/pkcs11 v0.0.0-20190322140431-074fd7a1ed19 // 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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1
|
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_golang v0.8.0 // indirect
|
||||||
github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612 // 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/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/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/cobra v0.0.3
|
||||||
github.com/spf13/pflag v1.0.3
|
github.com/spf13/pflag v1.0.3
|
||||||
github.com/spf13/viper v1.3.2 // indirect
|
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/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xeipuuv/gojsonschema v0.0.0-20160323030313-93e72a773fad // indirect
|
github.com/xeipuuv/gojsonschema v0.0.0-20160323030313-93e72a773fad // indirect
|
||||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 // 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
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||||
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
|
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
|
||||||
gopkg.in/fatih/pool.v2 v2.0.0 // 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 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
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.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||||
github.com/Microsoft/go-winio v0.4.13-0.20190408173621-84b4ab48a507/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
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.5/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
|
github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
|
||||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
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 h1:Qux+lbuMaRzkQyTdzgtz8MgzPtzmaPQy6DXmxpdxT3U=
|
||||||
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
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/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-20190717030353-c4b9ac5c7601 h1:6xW3ogNpFIly0umJGEKzFfGDNUk5rXFE1lJ3/gBmz3U=
|
||||||
github.com/containerd/cgroups v0.0.0-20190226200435-dbea6f2bd416/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
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 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-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 h1:GdiIYd8ZDOrT++e1NjhSD4rGt9zaJukHm4rt5F4mRQc=
|
||||||
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
|
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.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.4.0-0.20191014053712-acdcf13d5eaf h1:phUfu9w7+g1Vp149t3FThX2BmW+DkKkHj613PzZrQuU=
|
||||||
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/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-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 h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw=
|
||||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
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-20190816180239-bda0ff6ed73c h1:KFbqHhDeaHM7IfFtXHfUHMDaUStpM2YwBR+iJCIOsKk=
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4=
|
github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/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-cni v0.0.0-20190610170741-5a4663dad645/go.mod h1:2wlRxCQdiBY+OcjNg5x8kI+5mEL1fGt25L4IzQHYJsM=
|
|
||||||
github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
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-20190828172938-92c8520ef9f8 h1:jYCTS/16RWXXtVHNHo1KWNegd1kKQ7lHd7BStj/0hKw=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
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-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 h1:14r0i3IeJj6zkNLigAJiv/TWSR8EY+pxIjv5tFiT+n8=
|
||||||
github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
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/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-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-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-20190620071333-e64a0ec8b42a h1:W8b4lQ4tFF21aspRGoBuCNV6V2fFJBF+pm1J6OY8Lys=
|
||||||
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/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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@ -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/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 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
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 h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
|
||||||
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||||
github.com/gofrs/flock v0.7.0 h1:pGFUjl501gafK9HBt1VGL1KCOd/YhIooID+xgyJCf3g=
|
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/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 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0 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 h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
|
||||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
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=
|
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/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 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
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.20191022011428-4f4e03067523 h1:9kOZqIXIAb7oJEx551SdaIl110iwEpRB4teHPTOjIHc=
|
||||||
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/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 h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
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=
|
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 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.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-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.0.20190621203724-f4982d86f7fd h1:w9DJ/JL7fK4VjMoGo4e9gsq2xRhZThNI4PFuAwN8dJ0=
|
||||||
github.com/opencontainers/runc v1.0.0-rc8/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
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 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 h1:wY4pOY8fBdSIvs9+IDHC55thBuEulhzfSgKeC1yFvzQ=
|
||||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
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/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 h1:osmNoEW2SCW3L7EX0km2LYM8HKpNWRiouxjE3XHkyGc=
|
||||||
github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
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.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE=
|
||||||
github.com/prometheus/procfs v0.0.0-20180612222113-7d6f385de8be/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
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/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 h1:ka9QPuQg2u4LGipiZGsgkg3rJCo4iIUCy75FddM0GRQ=
|
||||||
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
|
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.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.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||||
github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
|
||||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
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/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
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 h1:j2hhcujLRHAg872RWAV5yaUrEjHEObwDv3aImCaNLek=
|
||||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
|
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=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
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-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-20190129210102-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
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-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 h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
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 h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
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-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-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-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-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-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 h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
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/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-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-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 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
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 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
|
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
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/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 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
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.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
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 h1:hROmpFC7JMobXFXMmD7ZKZLhDKvr1IKfFJoYS/45G/8=
|
||||||
k8s.io/api v0.0.0-20180712090710-2d6f90ab1293/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
|
k8s.io/api v0.0.0-20180712090710-2d6f90ab1293/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
|
||||||
k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d h1:MZjlsu9igBoVPZkXpIGoxI6EonqNsXXZU7hhvfQLkd4=
|
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 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 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 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
|
type atomicBool int32
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ type win32File struct {
|
|||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
wgLock sync.RWMutex
|
wgLock sync.RWMutex
|
||||||
closing atomicBool
|
closing atomicBool
|
||||||
|
socket bool
|
||||||
readDeadline deadlineHandler
|
readDeadline deadlineHandler
|
||||||
writeDeadline deadlineHandler
|
writeDeadline deadlineHandler
|
||||||
}
|
}
|
||||||
@ -109,7 +111,13 @@ func makeWin32File(h syscall.Handle) (*win32File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, 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
|
// 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() {
|
if f.closing.isSet() {
|
||||||
err = ErrFileClosed
|
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:
|
case <-timeout:
|
||||||
cancelIoEx(f.handle, &c.o)
|
cancelIoEx(f.handle, &c.o)
|
||||||
@ -265,6 +277,10 @@ func (f *win32File) Flush() error {
|
|||||||
return syscall.FlushFileBuffers(f.handle)
|
return syscall.FlushFileBuffers(f.handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *win32File) Fd() uintptr {
|
||||||
|
return uintptr(f.handle)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *deadlineHandler) set(deadline time.Time) error {
|
func (d *deadlineHandler) set(deadline time.Time) error {
|
||||||
d.setLock.Lock()
|
d.setLock.Lock()
|
||||||
defer d.setLock.Unlock()
|
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
|
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 (
|
var (
|
||||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ var (
|
|||||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||||
|
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
||||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||||
@ -73,6 +75,7 @@ var (
|
|||||||
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
||||||
procBackupRead = modkernel32.NewProc("BackupRead")
|
procBackupRead = modkernel32.NewProc("BackupRead")
|
||||||
procBackupWrite = modkernel32.NewProc("BackupWrite")
|
procBackupWrite = modkernel32.NewProc("BackupWrite")
|
||||||
|
procbind = modws2_32.NewProc("bind")
|
||||||
)
|
)
|
||||||
|
|
||||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||||
@ -124,6 +127,24 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
|
|||||||
return
|
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) {
|
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
||||||
if r1 == 0 {
|
if r1 == 0 {
|
||||||
@ -527,3 +548,15 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p
|
|||||||
}
|
}
|
||||||
return
|
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
|
GOPATH: C:\gopath
|
||||||
CGO_ENABLED: 1
|
CGO_ENABLED: 1
|
||||||
matrix:
|
matrix:
|
||||||
- GO_VERSION: 1.12.1
|
- GO_VERSION: 1.12.10
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
- choco install -y mingw --version 5.3.0
|
- choco install -y mingw --version 5.3.0
|
||||||
@ -54,9 +54,9 @@ test_script:
|
|||||||
# TODO: need an equivalent of TRAVIS_COMMIT_RANGE
|
# 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
|
# - 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 -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
|
# 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:
|
on_success:
|
||||||
codecov --flag windows -f coverage.txt
|
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>
|
||||||
Abhinandan Prativadi <abhi@docker.com> abhi <abhi@docker.com>
|
Abhinandan Prativadi <abhi@docker.com> <aprativadi@gmail.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> <suda.akihiro@lab.ntt.co.jp>
|
||||||
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
|
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.kyoto@gmail.com>
|
||||||
Andrei Vagin <avagin@virtuozzo.com> Andrei Vagin <avagin@openvz.org>
|
Andrei Vagin <avagin@virtuozzo.com> <avagin@openvz.org>
|
||||||
Brent Baude <bbaude@redhat.com> baude <bbaude@redhat.com>
|
Andrey Kolomentsev <andrey.kolomentsev@gmail.com>
|
||||||
Frank Yang <yyb196@gmail.com> frank yang <yyb196@gmail.com>
|
Brent Baude <bbaude@redhat.com>
|
||||||
Georgia Panoutsakopoulou <gpanoutsak@gmail.com> gpanouts <gpanoutsak@gmail.com>
|
Carlos Eduardo <me@carlosedp.com> <me@carlosedp.com>
|
||||||
Jie Zhang <iamkadisi@163.com> kadisi <iamkadisi@163.com>
|
Eric Ren <renzhen.rz@alibaba-linux.com> <renzhen.rz@alibaba-inc.com>
|
||||||
John Howard <john.howard@microsoft.com> John Howard <jhoward@microsoft.com>
|
Frank Yang <yyb196@gmail.com>
|
||||||
Justin Terry <juterry@microsoft.com> Justin Terry (VM) <juterry@microsoft.com>
|
Georgia Panoutsakopoulou <gpanoutsak@gmail.com>
|
||||||
Justin Terry <juterry@microsoft.com> Justin <jterry75@users.noreply.github.com>
|
Guangming Wang <guangming.wang@daocloud.io>
|
||||||
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com> Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
|
Haiyan Meng <haiyanmeng@google.com>
|
||||||
Kevin Xu <cming.xu@gmail.com> kevin.xu <cming.xu@gmail.com>
|
Jian Liao <jliao@alauda.io>
|
||||||
Lu Jingxiao <lujingxiao@huawei.com> l00397676 <lujingxiao@huawei.com>
|
Jian Liao <jliao@alauda.io> <liaojian@Dabllo.local>
|
||||||
Lantao Liu <lantaol@google.com> Lantao Liu <taotaotheripper@gmail.com>
|
Ji'an Liu <anthonyliu@zju.edu.cn>
|
||||||
Phil Estes <estesp@gmail.com> Phil Estes <estesp@linux.vnet.ibm.com>
|
Jie Zhang <iamkadisi@163.com>
|
||||||
Stephen J Day <stevvooe@gmail.com> Stephen J Day <stephen.day@docker.com>
|
John Howard <john.howard@microsoft.com> <jhoward@microsoft.com>
|
||||||
Stephen J Day <stevvooe@gmail.com> Stephen Day <stevvooe@users.noreply.github.com>
|
John Howard <john.howard@microsoft.com> <jhowardmsft@users.noreply.github.com>
|
||||||
Stephen J Day <stevvooe@gmail.com> Stephen Day <stephen.day@getcruise.com>
|
Julien Balestra <julien.balestra@datadoghq.com>
|
||||||
Sudeesh John <sudeesh@linux.vnet.ibm.com> sudeesh john <sudeesh@linux.vnet.ibm.com>
|
Justin Cormack <justin.cormack@docker.com> <justin@specialbusservice.com>
|
||||||
Tõnis Tiigi <tonistiigi@gmail.com> Tonis Tiigi <tonistiigi@gmail.com>
|
Justin Terry <juterry@microsoft.com>
|
||||||
Lifubang <lifubang@aliyun.com> Lifubang <lifubang@acmcoder.com>
|
Justin Terry <juterry@microsoft.com> <jterry75@users.noreply.github.com>
|
||||||
Xiaodong Zhang <a4012017@sina.com> nashasha1 <a4012017@sina.com>
|
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
||||||
Jian Liao <jliao@alauda.io> liaoj <jliao@alauda.io>
|
Kevin Xu <cming.xu@gmail.com>
|
||||||
Jian Liao <jliao@alauda.io> liaojian <liaojian@Dabllo.local>
|
Lantao Liu <lantaol@google.com> <taotaotheripper@gmail.com>
|
||||||
Rui Cao <ruicao@alauda.io> ruicao <ruicao@alauda.io>
|
Lifubang <lifubang@aliyun.com> <lifubang@acmcoder.com>
|
||||||
Xuean Yan <yan.xuean@zte.com.cn> yanxuean <yan.xuean@zte.com.cn>
|
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>
|
||||||
|
66
vendor/github.com/containerd/containerd/.travis.yml
generated
vendored
66
vendor/github.com/containerd/containerd/.travis.yml
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
dist: xenial
|
dist: bionic
|
||||||
sudo: required
|
sudo: required
|
||||||
# setup travis so that we can run containers for integration tests
|
# setup travis so that we can run containers for integration tests
|
||||||
services:
|
services:
|
||||||
@ -6,8 +6,25 @@ services:
|
|||||||
|
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
|
||||||
go:
|
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
|
go_import_path: github.com/containerd/containerd
|
||||||
|
|
||||||
@ -22,16 +39,9 @@ addons:
|
|||||||
- python-minimal
|
- python-minimal
|
||||||
- libcap-dev
|
- libcap-dev
|
||||||
- libaio-dev
|
- libaio-dev
|
||||||
- libprotobuf-c0-dev
|
- libprotobuf-c-dev
|
||||||
- libprotobuf-dev
|
- libprotobuf-dev
|
||||||
- socat
|
- 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:
|
before_install:
|
||||||
- uname -r
|
- uname -r
|
||||||
@ -45,12 +55,13 @@ install:
|
|||||||
- go get -u github.com/vbatts/git-validation
|
- go get -u github.com/vbatts/git-validation
|
||||||
- go get -u github.com/kunalkushwaha/ltag
|
- go get -u github.com/kunalkushwaha/ltag
|
||||||
- go get -u github.com/LK4D4/vndr
|
- 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-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-cni ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-critools ; 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 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
|
- cd $TRAVIS_BUILD_DIR
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
@ -61,21 +72,22 @@ script:
|
|||||||
- export CGO_ENABLED=$TRAVIS_CGO_ENABLED
|
- export CGO_ENABLED=$TRAVIS_CGO_ENABLED
|
||||||
- DCO_VERBOSITY=-q ../project/script/validate/dco
|
- DCO_VERBOSITY=-q ../project/script/validate/dco
|
||||||
- ../project/script/validate/fileheader ../project/
|
- ../project/script/validate/fileheader ../project/
|
||||||
- ../project/script/validate/vendor
|
- travis_wait ../project/script/validate/vendor
|
||||||
- GOOS=linux script/setup/install-dev-tools
|
- GOOS=linux script/setup/install-dev-tools
|
||||||
- go build -i .
|
- go build -i .
|
||||||
- make check
|
- make check
|
||||||
- if [ "$GOOS" = "linux" ]; then make check-protos check-api-descriptors; fi
|
- if [ "$GOOS" = "linux" ]; then make check-protos check-api-descriptors; fi
|
||||||
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then make man ; fi
|
||||||
- make build
|
- make build
|
||||||
- make binaries
|
- make binaries
|
||||||
- if [ "$GOOS" = "linux" ]; then sudo make install ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo make install ; fi
|
||||||
- if [ "$GOOS" = "linux" ]; then make coverage ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then make coverage ; fi
|
||||||
- if [ "$GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make root-coverage ; fi
|
- if [ "$TRAVIS_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 PATH=$PATH GOPATH=$GOPATH make integration ; fi
|
||||||
# Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759
|
# 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 mkdir -p /etc/containerd
|
||||||
sudo bash -c "cat > /etc/containerd/config.toml <<EOF
|
sudo bash -c "cat > /etc/containerd/config.toml <<EOF
|
||||||
[plugins.cri.containerd.default_runtime]
|
[plugins.cri.containerd.default_runtime]
|
||||||
@ -95,15 +107,25 @@ after_success:
|
|||||||
- bash <(curl -s https://codecov.io/bash) -F linux
|
- bash <(curl -s https://codecov.io/bash) -F linux
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- make release
|
- if [ "$TRAVIS_RELEASE" = "yes" ]; then make release cri-release; fi
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
provider: releases
|
- provider: releases
|
||||||
api_key:
|
api_key:
|
||||||
secure: HO+WSIVVUMMsbU74x+YyFsTP3ahqnR4xjwKAziedJ5lZXKJszQBhiYTFmcTeVBoouNjTISd07GQzpoLChuGC20U3+1NbT+CkK8xWR/x1ao2D3JY3Ds6AD9ubWRNWRLptt/xOn5Vq3F8xZyUYchwvDMl4zKCuTKxQGVdHKsINb2DehKcP5cVL6MMvqzEdfj2g99vqXAqs8uuo6dOmvxmHV43bfzDaAJSabjZZs6TKlWTqCQMet8uxyx2Dmjl2lxLwdqv12oJdrszacasn41NYuEyHI2bXyef1mhWGYN4n9bU/Y5winctZ8DOSOZvYg/2ziAaUN0+CTn1IESwVesrPz23P2Sy7wdLxu8dSIZ2yUHl7OsA5T5a5rDchAGguRVNBWvoGtuepEhdRacxTQUo1cMFZsEXjgRKKjdfc1emYQPVdN8mBv8GJwndty473ZXdvFt5R0kNVFtvWuYCa6UYJD2cKrsPSAfbZCDC/LiR3FOoTaUPMZUVkR2ACEO7Dn4+KlmBajqT40Osk/A7k1XA/TzVhMIpLtE0Vk2DfPmGsjCv8bC+MFd+R2Sc8SFdE92oEWRdoPQY5SxMYQtGxA+cbKVlT1kSw6y80yEbx5JZsBnT6+NTHwmDO3kVU9ztLdawOozTElKNAK8HoAyFmzIZ3wL64oThuDrv/TUuY8Iyn814=
|
secure: HO+WSIVVUMMsbU74x+YyFsTP3ahqnR4xjwKAziedJ5lZXKJszQBhiYTFmcTeVBoouNjTISd07GQzpoLChuGC20U3+1NbT+CkK8xWR/x1ao2D3JY3Ds6AD9ubWRNWRLptt/xOn5Vq3F8xZyUYchwvDMl4zKCuTKxQGVdHKsINb2DehKcP5cVL6MMvqzEdfj2g99vqXAqs8uuo6dOmvxmHV43bfzDaAJSabjZZs6TKlWTqCQMet8uxyx2Dmjl2lxLwdqv12oJdrszacasn41NYuEyHI2bXyef1mhWGYN4n9bU/Y5winctZ8DOSOZvYg/2ziAaUN0+CTn1IESwVesrPz23P2Sy7wdLxu8dSIZ2yUHl7OsA5T5a5rDchAGguRVNBWvoGtuepEhdRacxTQUo1cMFZsEXjgRKKjdfc1emYQPVdN8mBv8GJwndty473ZXdvFt5R0kNVFtvWuYCa6UYJD2cKrsPSAfbZCDC/LiR3FOoTaUPMZUVkR2ACEO7Dn4+KlmBajqT40Osk/A7k1XA/TzVhMIpLtE0Vk2DfPmGsjCv8bC+MFd+R2Sc8SFdE92oEWRdoPQY5SxMYQtGxA+cbKVlT1kSw6y80yEbx5JZsBnT6+NTHwmDO3kVU9ztLdawOozTElKNAK8HoAyFmzIZ3wL64oThuDrv/TUuY8Iyn814=
|
||||||
file_glob: true
|
file_glob: true
|
||||||
file: releases/*.tar.gz
|
file:
|
||||||
|
- releases/*.tar.gz
|
||||||
|
- releases/*.tar.gz.sha256sum
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
on:
|
on:
|
||||||
repo: containerd/containerd
|
repo: containerd/containerd
|
||||||
tags: true
|
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))))
|
ROOTDIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
|
||||||
# Base path used to install.
|
# Base path used to install.
|
||||||
DESTDIR=/usr/local
|
DESTDIR ?= /usr/local
|
||||||
|
|
||||||
# Used to populate variables in version package.
|
# Used to populate variables in version package.
|
||||||
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always)
|
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always)
|
||||||
@ -111,17 +111,17 @@ GO_GCFLAGS=$(shell \
|
|||||||
BINARIES=$(addprefix bin/,$(COMMANDS))
|
BINARIES=$(addprefix bin/,$(COMMANDS))
|
||||||
|
|
||||||
# Flags passed to `go test`
|
# Flags passed to `go test`
|
||||||
TESTFLAGS ?= -v $(TESTFLAGS_RACE)
|
TESTFLAGS ?= $(TESTFLAGS_RACE)
|
||||||
TESTFLAGS_PARALLEL ?= 8
|
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
|
.DEFAULT: default
|
||||||
|
|
||||||
all: binaries
|
all: binaries
|
||||||
|
|
||||||
check: proto-fmt ## run all linters
|
check: proto-fmt ## run all linters
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
gometalinter --config .gometalinter.json ./...
|
GOGC=75 golangci-lint run
|
||||||
|
|
||||||
ci: check binaries checkprotos coverage coverage-integration ## to be used by the CI
|
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"
|
@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
|
@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
|
binaries: $(BINARIES) ## build binaries
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
|
|
||||||
@ -207,8 +203,19 @@ man: mandir $(addprefix man/,$(MANPAGES))
|
|||||||
mandir:
|
mandir:
|
||||||
@mkdir -p man
|
@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
|
man/%: docs/man/%.md FORCE
|
||||||
@echo "$(WHALE) $<"
|
@echo "$(WHALE) $@"
|
||||||
go-md2man -in "$<" -out "$@"
|
go-md2man -in "$<" -out "$@"
|
||||||
|
|
||||||
define installmanpage
|
define installmanpage
|
||||||
@ -220,12 +227,21 @@ install-man:
|
|||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
$(foreach manpage,$(addprefix man/,$(MANPAGES)), $(call installmanpage,$(manpage),$(subst .,,$(suffix $(manpage))),$(notdir $(manpage))))
|
$(foreach manpage,$(addprefix man/,$(MANPAGES)), $(call installmanpage,$(manpage),$(subst .,,$(suffix $(manpage))),$(notdir $(manpage))))
|
||||||
|
|
||||||
release: $(BINARIES)
|
releases/$(RELEASE).tar.gz: $(BINARIES)
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@rm -rf releases/$(RELEASE) releases/$(RELEASE).tar.gz
|
@rm -rf releases/$(RELEASE) releases/$(RELEASE).tar.gz
|
||||||
@install -d releases/$(RELEASE)/bin
|
@install -d releases/$(RELEASE)/bin
|
||||||
@install $(BINARIES) 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
|
clean: ## clean up binaries
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@ -286,7 +302,7 @@ root-coverage: ## generate coverage profiles for unit tests that require root
|
|||||||
|
|
||||||
vendor:
|
vendor:
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@vndr
|
@vndr -whitelist github.com/urfave/cli/autocomplete/
|
||||||
|
|
||||||
help: ## this help
|
help: ## this help
|
||||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
|
@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.
|
#Windows specific settings.
|
||||||
WHALE = "+"
|
WHALE = "+"
|
||||||
ONI = "-"
|
ONI = "-"
|
||||||
COMMANDS += containerd-shim-runhcs-v1
|
|
||||||
|
|
||||||
BINARY_SUFFIX=".exe"
|
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",
|
"google/protobuf/descriptor.proto",
|
||||||
"gogoproto/gogo.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
|
Please see [RELEASES.md](RELEASES.md) for details on versioning and stability
|
||||||
of containerd components.
|
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
|
### Communication
|
||||||
|
|
||||||
For async communication and long running discussions please use issues and pull requests on the github repo.
|
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.
|
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.
|
**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
|
### 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:
|
by `<major>.<minor>`. Releases branches will be in one of several states:
|
||||||
|
|
||||||
- __*Next*__: The next planned release branch.
|
- __*Next*__: The next planned release branch.
|
||||||
- __*Active*__: The release is currently supported and accepting patches.
|
- __*Active*__: The release branch is currently supported and accepting patches.
|
||||||
- __*Extended*__: The release is only accepting security 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.
|
- __*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
|
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.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 |
|
| [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.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.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.6) | Active | October 24, 2018 | max(October 24, 2019, release of 1.3.0 + 6 months) |
|
| [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/milestone/20) | Next | TBD | max(TBD+1 year, release of 1.4.0 + 6 months) |
|
| [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.
|
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) |
|
| GRPC API | Stable | 1.0 | [api/](api) |
|
||||||
| Metrics API | Stable | 1.0 | - |
|
| Metrics API | Stable | 1.0 | - |
|
||||||
| Runtime Shim API | Stable | 1.2 | - |
|
| Runtime Shim API | Stable | 1.2 | - |
|
||||||
|
| Daemon Config | Stable | 1.0 | - |
|
||||||
| Go client API | Unstable | _future_ | [godoc](https://godoc.org/github.com/containerd/containerd) |
|
| 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) |
|
| 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 | - |
|
| `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
|
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.
|
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
|
### Metrics API
|
||||||
|
|
||||||
The metrics API that outputs prometheus style metrics will be versioned independently,
|
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
|
### `ctr` tool
|
||||||
|
|
||||||
The `ctr` tool provides the ability to introspect and understand the containerd
|
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
|
API. It is not considered a primary offering of the project and is unsupported in
|
||||||
may be completely refactored or have breaking changes in _minor_ releases.
|
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
|
### Not Covered
|
||||||
|
|
||||||
|
256
vendor/github.com/containerd/containerd/api/services/diff/v1/diff.pb.go
generated
vendored
256
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"
|
types "github.com/containerd/containerd/api/types"
|
||||||
proto "github.com/gogo/protobuf/proto"
|
proto "github.com/gogo/protobuf/proto"
|
||||||
github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||||
|
types1 "github.com/gogo/protobuf/types"
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
io "io"
|
io "io"
|
||||||
math "math"
|
math "math"
|
||||||
@ -31,6 +32,7 @@ type ApplyRequest struct {
|
|||||||
// Diff is the descriptor of the diff to be extracted
|
// Diff is the descriptor of the diff to be extracted
|
||||||
Diff *types.Descriptor `protobuf:"bytes,1,opt,name=diff,proto3" json:"diff,omitempty"`
|
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"`
|
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_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
XXX_sizecache int32 `json:"-"`
|
XXX_sizecache int32 `json:"-"`
|
||||||
@ -205,6 +207,7 @@ var xxx_messageInfo_DiffResponse proto.InternalMessageInfo
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*ApplyRequest)(nil), "containerd.services.diff.v1.ApplyRequest")
|
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((*ApplyResponse)(nil), "containerd.services.diff.v1.ApplyResponse")
|
||||||
proto.RegisterType((*DiffRequest)(nil), "containerd.services.diff.v1.DiffRequest")
|
proto.RegisterType((*DiffRequest)(nil), "containerd.services.diff.v1.DiffRequest")
|
||||||
proto.RegisterMapType((map[string]string)(nil), "containerd.services.diff.v1.DiffRequest.LabelsEntry")
|
proto.RegisterMapType((map[string]string)(nil), "containerd.services.diff.v1.DiffRequest.LabelsEntry")
|
||||||
@ -216,36 +219,40 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_3b36a99e6faaa935 = []byte{
|
var fileDescriptor_3b36a99e6faaa935 = []byte{
|
||||||
// 457 bytes of a gzipped FileDescriptorProto
|
// 526 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x4f, 0x6f, 0xd3, 0x30,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x41, 0x6f, 0xd3, 0x4c,
|
||||||
0x14, 0xaf, 0xfb, 0x0f, 0xf5, 0x75, 0x48, 0xc8, 0x9a, 0x44, 0x14, 0x20, 0xaa, 0x7a, 0xea, 0x40,
|
0x10, 0x8d, 0xed, 0x24, 0xdf, 0x97, 0x49, 0x2b, 0xa1, 0x55, 0x24, 0x8c, 0x01, 0xab, 0xca, 0x29,
|
||||||
0x38, 0xac, 0xa0, 0x09, 0xb6, 0xcb, 0x40, 0x43, 0x5c, 0xc6, 0x25, 0xda, 0x01, 0x81, 0x04, 0x4a,
|
0x2d, 0x62, 0x4d, 0x03, 0x2a, 0xd0, 0x5e, 0x5a, 0x54, 0xc4, 0xa5, 0x48, 0x60, 0x7a, 0x40, 0x20,
|
||||||
0x9b, 0x97, 0xce, 0x22, 0x8d, 0xbd, 0xd8, 0xad, 0x94, 0x1b, 0xdf, 0x85, 0x8f, 0xc2, 0x65, 0x47,
|
0x81, 0x9c, 0x78, 0xed, 0xae, 0x70, 0xbc, 0x8b, 0x77, 0x1d, 0xc9, 0x37, 0xfe, 0x06, 0x67, 0x7e,
|
||||||
0x8e, 0x1c, 0x69, 0x3f, 0x09, 0xb2, 0x93, 0x40, 0x24, 0xa4, 0x12, 0x76, 0xca, 0xcb, 0xf3, 0xef,
|
0x0a, 0x97, 0x1e, 0x39, 0x72, 0xa4, 0xf9, 0x25, 0xc8, 0xeb, 0x75, 0x31, 0x02, 0x05, 0xc3, 0xc9,
|
||||||
0x9f, 0xfd, 0x6c, 0x38, 0x5d, 0x70, 0x7d, 0xb9, 0x9a, 0xb1, 0xb9, 0x58, 0xfa, 0x73, 0x91, 0xea,
|
0x9b, 0x9d, 0xf7, 0xde, 0xce, 0xbc, 0x37, 0x0a, 0x1c, 0xc6, 0x54, 0x9e, 0xe5, 0x33, 0x3c, 0x67,
|
||||||
0x90, 0xa7, 0x98, 0x45, 0xf5, 0x32, 0x94, 0xdc, 0x57, 0x98, 0xad, 0xf9, 0x1c, 0x95, 0x1f, 0xf1,
|
0x0b, 0x6f, 0xce, 0x52, 0x19, 0xd0, 0x94, 0x64, 0x61, 0xf3, 0x18, 0x70, 0xea, 0x09, 0x92, 0x2d,
|
||||||
0x38, 0xf6, 0xd7, 0x87, 0xf6, 0xcb, 0x64, 0x26, 0xb4, 0xa0, 0xf7, 0xfe, 0x60, 0x59, 0x85, 0x63,
|
0xe9, 0x9c, 0x08, 0x2f, 0xa4, 0x51, 0xe4, 0x2d, 0x77, 0xd5, 0x17, 0xf3, 0x8c, 0x49, 0x86, 0xae,
|
||||||
0x76, 0x7d, 0x7d, 0xe8, 0xee, 0x2f, 0xc4, 0x42, 0x58, 0x9c, 0x6f, 0xaa, 0x82, 0xe2, 0x1e, 0x35,
|
0xff, 0xc0, 0xe2, 0x1a, 0x87, 0x55, 0x7d, 0xb9, 0xeb, 0x8c, 0x62, 0x16, 0x33, 0x85, 0xf3, 0xca,
|
||||||
0x32, 0xd5, 0xb9, 0x44, 0xe5, 0x2f, 0xc5, 0x2a, 0xd5, 0x25, 0xef, 0xe4, 0x3f, 0x78, 0x11, 0xaa,
|
0x53, 0x45, 0x71, 0xae, 0xc5, 0x8c, 0xc5, 0x09, 0xf1, 0xd4, 0xaf, 0x59, 0x1e, 0x79, 0x41, 0x5a,
|
||||||
0x79, 0xc6, 0xa5, 0x16, 0x59, 0x41, 0x1e, 0x5f, 0xc1, 0xde, 0x4b, 0x29, 0x93, 0x3c, 0xc0, 0xab,
|
0xe8, 0xd2, 0x5e, 0xab, 0x7e, 0x64, 0xc1, 0x89, 0xf0, 0x16, 0x2c, 0x4f, 0xa5, 0xe6, 0x1d, 0xfc,
|
||||||
0x15, 0x2a, 0x4d, 0x9f, 0x40, 0xd7, 0xa4, 0x74, 0xc8, 0x88, 0x4c, 0x86, 0xd3, 0xfb, 0xac, 0xb6,
|
0x05, 0x2f, 0x24, 0x62, 0x9e, 0x51, 0x2e, 0x59, 0x56, 0x91, 0xc7, 0x1f, 0x4d, 0xd8, 0x38, 0xe2,
|
||||||
0x0d, 0xab, 0xc0, 0xce, 0x7e, 0x2b, 0x04, 0x16, 0x49, 0x7d, 0xe8, 0xdb, 0x34, 0xca, 0x69, 0x8f,
|
0x3c, 0x29, 0x7c, 0xf2, 0x3e, 0x27, 0x42, 0xa2, 0x3b, 0xd0, 0x2d, 0x27, 0xb0, 0x8d, 0x2d, 0x63,
|
||||||
0x3a, 0x93, 0xe1, 0xf4, 0xee, 0xdf, 0x9c, 0xb7, 0x66, 0x3d, 0x28, 0x61, 0xe3, 0x37, 0x70, 0xbb,
|
0x32, 0x9c, 0xde, 0xc0, 0x8d, 0x11, 0x95, 0x04, 0x3e, 0xbe, 0x94, 0xf0, 0x15, 0x12, 0x79, 0xd0,
|
||||||
0xb4, 0x54, 0x52, 0xa4, 0x0a, 0xe9, 0x11, 0xdc, 0x0a, 0xa5, 0x4c, 0x38, 0x46, 0x8d, 0x6c, 0x2b,
|
0x57, 0xed, 0x08, 0xdb, 0xdc, 0xb2, 0x26, 0xc3, 0xe9, 0xd5, 0x5f, 0x39, 0x4f, 0xcb, 0xba, 0xaf,
|
||||||
0xf0, 0xf8, 0x6b, 0x1b, 0x86, 0x67, 0x3c, 0x8e, 0xab, 0xec, 0x8f, 0xa0, 0x9b, 0x60, 0xac, 0x1d,
|
0x61, 0xe8, 0x05, 0xfc, 0xcf, 0x83, 0x22, 0x61, 0x41, 0x28, 0x6c, 0x4b, 0x51, 0xee, 0xe3, 0x35,
|
||||||
0xb2, 0x3b, 0x87, 0x05, 0xd1, 0xc7, 0xd0, 0xcb, 0xf8, 0xe2, 0x52, 0xff, 0x2b, 0x75, 0x81, 0xa2,
|
0x4e, 0xe2, 0x66, 0x7f, 0xf8, 0x99, 0x66, 0x3e, 0x4e, 0x65, 0x56, 0xf8, 0x97, 0x42, 0xce, 0x73,
|
||||||
0x0f, 0x00, 0x96, 0x18, 0xf1, 0xf0, 0x93, 0x59, 0x73, 0x3a, 0x23, 0x32, 0x19, 0x04, 0x03, 0xdb,
|
0xd8, 0xfc, 0xa9, 0x84, 0xae, 0x80, 0xf5, 0x8e, 0x14, 0x6a, 0x8e, 0x81, 0x5f, 0x1e, 0xd1, 0x0e,
|
||||||
0xb9, 0xc8, 0x25, 0xd2, 0x3b, 0xd0, 0xc9, 0x30, 0x76, 0xba, 0xb6, 0x6f, 0x4a, 0x7a, 0x0e, 0xfd,
|
0xf4, 0x96, 0x41, 0x92, 0x13, 0xdb, 0x54, 0xb3, 0x8d, 0x70, 0x95, 0x05, 0xae, 0xb3, 0xc0, 0x47,
|
||||||
0x24, 0x9c, 0x61, 0xa2, 0x9c, 0x9e, 0x35, 0x78, 0xc6, 0x76, 0xdc, 0x08, 0x56, 0xdb, 0x06, 0x3b,
|
0x69, 0xe1, 0x57, 0x90, 0x7d, 0xf3, 0x81, 0x31, 0x7e, 0x02, 0x9b, 0xfa, 0x69, 0xc1, 0x59, 0x2a,
|
||||||
0xb7, 0xb4, 0xd7, 0xa9, 0xce, 0xf2, 0xa0, 0xd4, 0x70, 0x5f, 0xc0, 0xb0, 0xd6, 0x36, 0x76, 0x9f,
|
0x08, 0xda, 0x83, 0xff, 0x02, 0xce, 0x13, 0x4a, 0xc2, 0x56, 0xf6, 0xd4, 0xe0, 0xf1, 0x27, 0x13,
|
||||||
0x31, 0xb7, 0xa7, 0x35, 0x08, 0x4c, 0x49, 0xf7, 0xa1, 0xb7, 0x0e, 0x93, 0x15, 0x3a, 0x6d, 0xdb,
|
0x86, 0xc7, 0x34, 0x8a, 0x6a, 0x8f, 0x6f, 0x41, 0x37, 0x21, 0x91, 0xb4, 0x8d, 0xf5, 0x7e, 0x29,
|
||||||
0x2b, 0x7e, 0x8e, 0xdb, 0xcf, 0xc9, 0xf8, 0x14, 0xf6, 0x0a, 0xf5, 0xf2, 0xb4, 0xab, 0x09, 0x77,
|
0x10, 0xba, 0x0d, 0xbd, 0x8c, 0xc6, 0x67, 0xf2, 0x4f, 0xee, 0x56, 0x28, 0x74, 0x13, 0x60, 0x41,
|
||||||
0x9a, 0x4e, 0x78, 0xfa, 0x8d, 0x40, 0xd7, 0x48, 0xd0, 0x8f, 0xd0, 0xb3, 0x93, 0xa3, 0x07, 0x3b,
|
0x42, 0x1a, 0xbc, 0x2d, 0x6b, 0xb6, 0xa5, 0xa6, 0x1f, 0xa8, 0x9b, 0xd3, 0x82, 0x93, 0xd2, 0x95,
|
||||||
0x37, 0x53, 0xbf, 0x50, 0xee, 0xc3, 0x26, 0xd0, 0x32, 0xda, 0x87, 0xd2, 0x67, 0xd2, 0xf4, 0xac,
|
0x8c, 0x44, 0x76, 0xb7, 0x72, 0x25, 0x23, 0x11, 0x3a, 0x81, 0x7e, 0x12, 0xcc, 0x48, 0x22, 0xec,
|
||||||
0xdc, 0x83, 0x06, 0xc8, 0x42, 0xfc, 0xd5, 0xc5, 0xf5, 0xc6, 0x6b, 0xfd, 0xd8, 0x78, 0xad, 0x2f,
|
0x9e, 0x7a, 0xe0, 0xde, 0xda, 0x2c, 0x1a, 0x63, 0xe0, 0x13, 0x45, 0xab, 0x82, 0xd0, 0x1a, 0xce,
|
||||||
0x5b, 0x8f, 0x5c, 0x6f, 0x3d, 0xf2, 0x7d, 0xeb, 0x91, 0x9f, 0x5b, 0x8f, 0xbc, 0x3f, 0xbe, 0xd1,
|
0x43, 0x18, 0x36, 0xae, 0x7f, 0x13, 0xc2, 0xa8, 0x19, 0xc2, 0xa0, 0x69, 0xf7, 0x21, 0x6c, 0x54,
|
||||||
0x6b, 0x3f, 0x31, 0xdf, 0x77, 0xad, 0x59, 0xdf, 0x3e, 0xa4, 0xa7, 0xbf, 0x02, 0x00, 0x00, 0xff,
|
0xea, 0xda, 0xed, 0x7a, 0x13, 0xad, 0xb6, 0x9b, 0x38, 0xfd, 0x6c, 0x40, 0xb7, 0x94, 0x40, 0x6f,
|
||||||
0xff, 0x61, 0xd1, 0x6e, 0x9e, 0x34, 0x04, 0x00, 0x00,
|
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.
|
// 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
|
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 {
|
if m.XXX_unrecognized != nil {
|
||||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||||
}
|
}
|
||||||
@ -425,11 +460,11 @@ func (m *ApplyResponse) MarshalTo(dAtA []byte) (int, error) {
|
|||||||
dAtA[i] = 0xa
|
dAtA[i] = 0xa
|
||||||
i++
|
i++
|
||||||
i = encodeVarintDiff(dAtA, i, uint64(m.Applied.Size()))
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
i += n2
|
i += n3
|
||||||
}
|
}
|
||||||
if m.XXX_unrecognized != nil {
|
if m.XXX_unrecognized != nil {
|
||||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||||
@ -530,11 +565,11 @@ func (m *DiffResponse) MarshalTo(dAtA []byte) (int, error) {
|
|||||||
dAtA[i] = 0x1a
|
dAtA[i] = 0x1a
|
||||||
i++
|
i++
|
||||||
i = encodeVarintDiff(dAtA, i, uint64(m.Diff.Size()))
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
i += n3
|
i += n4
|
||||||
}
|
}
|
||||||
if m.XXX_unrecognized != nil {
|
if m.XXX_unrecognized != nil {
|
||||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||||
@ -567,6 +602,19 @@ func (m *ApplyRequest) Size() (n int) {
|
|||||||
n += 1 + l + sovDiff(uint64(l))
|
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 {
|
if m.XXX_unrecognized != nil {
|
||||||
n += len(m.XXX_unrecognized)
|
n += len(m.XXX_unrecognized)
|
||||||
}
|
}
|
||||||
@ -662,9 +710,20 @@ func (this *ApplyRequest) String() string {
|
|||||||
if this == nil {
|
if this == nil {
|
||||||
return "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{`,
|
s := strings.Join([]string{`&ApplyRequest{`,
|
||||||
`Diff:` + strings.Replace(fmt.Sprintf("%v", this.Diff), "Descriptor", "types.Descriptor", 1) + `,`,
|
`Diff:` + strings.Replace(fmt.Sprintf("%v", this.Diff), "Descriptor", "types.Descriptor", 1) + `,`,
|
||||||
`Mounts:` + strings.Replace(fmt.Sprintf("%v", this.Mounts), "Mount", "types.Mount", 1) + `,`,
|
`Mounts:` + strings.Replace(fmt.Sprintf("%v", this.Mounts), "Mount", "types.Mount", 1) + `,`,
|
||||||
|
`Payloads:` + mapStringForPayloads + `,`,
|
||||||
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
|
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
|
||||||
`}`,
|
`}`,
|
||||||
}, "")
|
}, "")
|
||||||
@ -824,6 +883,135 @@ func (m *ApplyRequest) Unmarshal(dAtA []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
iNdEx = postIndex
|
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:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipDiff(dAtA[iNdEx:])
|
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;
|
package containerd.services.diff.v1;
|
||||||
|
|
||||||
import weak "gogoproto/gogo.proto";
|
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/mount.proto";
|
||||||
import "github.com/containerd/containerd/api/types/descriptor.proto";
|
import "github.com/containerd/containerd/api/types/descriptor.proto";
|
||||||
|
|
||||||
@ -25,6 +26,8 @@ message ApplyRequest {
|
|||||||
containerd.types.Descriptor diff = 1;
|
containerd.types.Descriptor diff = 1;
|
||||||
|
|
||||||
repeated containerd.types.Mount mounts = 2;
|
repeated containerd.types.Mount mounts = 2;
|
||||||
|
|
||||||
|
map<string, google.protobuf.Any> payloads = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ApplyResponse {
|
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"
|
rpc "github.com/gogo/googleapis/google/rpc"
|
||||||
proto "github.com/gogo/protobuf/proto"
|
proto "github.com/gogo/protobuf/proto"
|
||||||
github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||||
|
types1 "github.com/gogo/protobuf/types"
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
io "io"
|
io "io"
|
||||||
math "math"
|
math "math"
|
||||||
@ -191,11 +192,51 @@ func (m *PluginsResponse) XXX_DiscardUnknown() {
|
|||||||
|
|
||||||
var xxx_messageInfo_PluginsResponse proto.InternalMessageInfo
|
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() {
|
func init() {
|
||||||
proto.RegisterType((*Plugin)(nil), "containerd.services.introspection.v1.Plugin")
|
proto.RegisterType((*Plugin)(nil), "containerd.services.introspection.v1.Plugin")
|
||||||
proto.RegisterMapType((map[string]string)(nil), "containerd.services.introspection.v1.Plugin.ExportsEntry")
|
proto.RegisterMapType((map[string]string)(nil), "containerd.services.introspection.v1.Plugin.ExportsEntry")
|
||||||
proto.RegisterType((*PluginsRequest)(nil), "containerd.services.introspection.v1.PluginsRequest")
|
proto.RegisterType((*PluginsRequest)(nil), "containerd.services.introspection.v1.PluginsRequest")
|
||||||
proto.RegisterType((*PluginsResponse)(nil), "containerd.services.introspection.v1.PluginsResponse")
|
proto.RegisterType((*PluginsResponse)(nil), "containerd.services.introspection.v1.PluginsResponse")
|
||||||
|
proto.RegisterType((*ServerResponse)(nil), "containerd.services.introspection.v1.ServerResponse")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -203,38 +244,42 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_1a14fda866f10715 = []byte{
|
var fileDescriptor_1a14fda866f10715 = []byte{
|
||||||
// 487 bytes of a gzipped FileDescriptorProto
|
// 549 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4d, 0x6f, 0xd3, 0x40,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xc1, 0x6e, 0xd3, 0x40,
|
||||||
0x10, 0xcd, 0x3a, 0x69, 0xdc, 0x4c, 0xca, 0x87, 0x56, 0x15, 0x58, 0x3e, 0xb8, 0x51, 0xc4, 0x21,
|
0x10, 0xad, 0x9d, 0x34, 0x6e, 0x37, 0xa5, 0xa0, 0x55, 0x55, 0x2c, 0x83, 0x9c, 0x28, 0xe2, 0x10,
|
||||||
0x42, 0xb0, 0x56, 0x03, 0x48, 0xb4, 0x48, 0x1c, 0x22, 0x72, 0xa8, 0xd4, 0x43, 0xe5, 0x5e, 0x10,
|
0x21, 0x58, 0xab, 0x01, 0x24, 0x5a, 0x24, 0x0e, 0x51, 0x73, 0x88, 0xd4, 0x43, 0xe5, 0xa8, 0x08,
|
||||||
0x97, 0xca, 0x71, 0x36, 0x66, 0x85, 0xeb, 0xdd, 0xee, 0xae, 0x2d, 0x72, 0xe3, 0xc6, 0x5f, 0xcb,
|
0x71, 0xa9, 0x1c, 0x67, 0x63, 0x56, 0x38, 0xde, 0xed, 0xee, 0xda, 0x22, 0x37, 0x3e, 0x2f, 0x47,
|
||||||
0x91, 0x23, 0xa7, 0x8a, 0xfa, 0x37, 0xf0, 0x03, 0x90, 0xbd, 0x76, 0x9b, 0xdc, 0x12, 0x71, 0x9b,
|
0x8e, 0x9c, 0x02, 0xf5, 0x37, 0xf0, 0x01, 0xc8, 0xbb, 0x76, 0x9a, 0xdc, 0x12, 0x71, 0x9b, 0x79,
|
||||||
0x79, 0x7e, 0x6f, 0xe6, 0xcd, 0x93, 0x17, 0x82, 0x98, 0xe9, 0xaf, 0xd9, 0x8c, 0x44, 0xfc, 0xda,
|
0x33, 0x6f, 0xe6, 0xcd, 0xf3, 0xca, 0xc0, 0x8f, 0x88, 0xfc, 0x9a, 0x8e, 0x51, 0x48, 0x67, 0x5e,
|
||||||
0x8f, 0x78, 0xaa, 0x43, 0x96, 0x52, 0x39, 0x5f, 0x2f, 0x43, 0xc1, 0x7c, 0x45, 0x65, 0xce, 0x22,
|
0x48, 0x13, 0x19, 0x90, 0x04, 0xf3, 0xc9, 0x7a, 0x18, 0x30, 0xe2, 0x09, 0xcc, 0x33, 0x12, 0x62,
|
||||||
0xaa, 0x7c, 0x96, 0x6a, 0xc9, 0x95, 0xa0, 0x91, 0x66, 0x3c, 0xf5, 0xf3, 0xe3, 0x4d, 0x80, 0x08,
|
0xe1, 0x91, 0x44, 0x72, 0x2a, 0x18, 0x0e, 0x25, 0xa1, 0x89, 0x97, 0x9d, 0x6d, 0x02, 0x88, 0x71,
|
||||||
0xc9, 0x35, 0xc7, 0x2f, 0x1e, 0xd4, 0xa4, 0x51, 0x92, 0x4d, 0x62, 0x7e, 0xec, 0x9e, 0x6c, 0xb5,
|
0x2a, 0x29, 0x7c, 0xf1, 0xc0, 0x46, 0x15, 0x13, 0x6d, 0x36, 0x66, 0x67, 0xce, 0xf9, 0x56, 0x9b,
|
||||||
0x59, 0x2f, 0x05, 0x55, 0xbe, 0x48, 0x42, 0xbd, 0xe0, 0xf2, 0xda, 0x2c, 0x70, 0x9f, 0xc7, 0x9c,
|
0xe5, 0x9c, 0x61, 0xe1, 0xb1, 0x38, 0x90, 0x53, 0xca, 0x67, 0x7a, 0x81, 0xf3, 0x34, 0xa2, 0x34,
|
||||||
0xc7, 0x09, 0xf5, 0xa5, 0x88, 0x7c, 0xa5, 0x43, 0x9d, 0xa9, 0xfa, 0xc3, 0x61, 0xcc, 0x63, 0x5e,
|
0x8a, 0xb1, 0xc7, 0x59, 0xe8, 0x09, 0x19, 0xc8, 0x54, 0x94, 0x85, 0x67, 0x65, 0x41, 0x65, 0xe3,
|
||||||
0x95, 0x7e, 0x59, 0x19, 0x74, 0xf8, 0xd7, 0x82, 0xee, 0x45, 0x92, 0xc5, 0x2c, 0xc5, 0x18, 0x3a,
|
0x74, 0xea, 0xe1, 0x19, 0x93, 0xf3, 0xb2, 0x78, 0x12, 0xd1, 0x88, 0xaa, 0xd0, 0x2b, 0x22, 0x8d,
|
||||||
0xe5, 0x44, 0x07, 0x0d, 0xd0, 0xa8, 0x17, 0x54, 0x35, 0x7e, 0x06, 0x16, 0x9b, 0x3b, 0x56, 0x89,
|
0x76, 0xfe, 0x9a, 0xa0, 0x71, 0x1d, 0xa7, 0x11, 0x49, 0x20, 0x04, 0xf5, 0x62, 0x9d, 0x6d, 0xb4,
|
||||||
0x4c, 0xba, 0xc5, 0xed, 0x91, 0x75, 0xf6, 0x29, 0xb0, 0xd8, 0x1c, 0xbb, 0xb0, 0x2f, 0xe9, 0x4d,
|
0x8d, 0xee, 0xa1, 0xaf, 0x62, 0x78, 0x0a, 0x4c, 0x32, 0xb1, 0xcd, 0x02, 0xe9, 0x37, 0xf2, 0x65,
|
||||||
0xc6, 0x24, 0x55, 0x4e, 0x7b, 0xd0, 0x1e, 0xf5, 0x82, 0xfb, 0x1e, 0x7f, 0x84, 0x5e, 0xe3, 0x49,
|
0xcb, 0x1c, 0x5e, 0xfa, 0x26, 0x99, 0x40, 0x07, 0x1c, 0x70, 0x7c, 0x97, 0x12, 0x8e, 0x85, 0x5d,
|
||||||
0x39, 0x9d, 0x41, 0x7b, 0xd4, 0x1f, 0xbb, 0x64, 0xed, 0xec, 0xca, 0x36, 0xb9, 0xa8, 0x29, 0x93,
|
0x6b, 0xd7, 0xba, 0x87, 0xfe, 0x2a, 0x87, 0x1f, 0xc1, 0x61, 0x25, 0x58, 0xd8, 0xf5, 0x76, 0xad,
|
||||||
0xce, 0xea, 0xf6, 0xa8, 0x15, 0x3c, 0x48, 0xf0, 0x25, 0xd8, 0xf4, 0xbb, 0xe0, 0x52, 0x2b, 0x67,
|
0xdb, 0xec, 0x39, 0x68, 0xcd, 0x13, 0x75, 0x13, 0xba, 0x2e, 0x5b, 0xfa, 0xf5, 0xc5, 0xb2, 0xb5,
|
||||||
0xaf, 0x52, 0x9f, 0x90, 0x6d, 0x42, 0x23, 0xe6, 0x0c, 0x32, 0x35, 0xda, 0x69, 0xaa, 0xe5, 0x32,
|
0xe7, 0x3f, 0x50, 0xe0, 0x08, 0x58, 0xf8, 0x3b, 0xa3, 0x5c, 0x0a, 0x7b, 0x5f, 0xb1, 0xcf, 0xd1,
|
||||||
0x68, 0x26, 0xe1, 0x21, 0x1c, 0x44, 0xa1, 0x08, 0x67, 0x2c, 0x61, 0x9a, 0x51, 0xe5, 0x74, 0x2b,
|
0x36, 0x8e, 0x22, 0x7d, 0x06, 0x1a, 0x68, 0xee, 0x20, 0x91, 0x7c, 0xee, 0x57, 0x93, 0x60, 0x07,
|
||||||
0xd3, 0x1b, 0x18, 0x7e, 0x0d, 0xfb, 0x2c, 0x65, 0xfa, 0x8a, 0x4a, 0xe9, 0xd8, 0x03, 0x34, 0xea,
|
0x1c, 0x85, 0x01, 0x0b, 0xc6, 0x24, 0x26, 0x92, 0x60, 0x61, 0x37, 0x94, 0xe8, 0x0d, 0x0c, 0xbe,
|
||||||
0x8f, 0x31, 0x31, 0x69, 0x12, 0x29, 0x22, 0x72, 0x59, 0xa5, 0x19, 0xd8, 0x25, 0x67, 0x2a, 0xa5,
|
0x06, 0x07, 0x24, 0x21, 0xf2, 0x16, 0x73, 0x6e, 0x5b, 0x6d, 0xa3, 0xdb, 0xec, 0x41, 0xa4, 0x1d,
|
||||||
0x7b, 0x0a, 0x07, 0xeb, 0xbb, 0xf0, 0x53, 0x68, 0x7f, 0xa3, 0xcb, 0x3a, 0xbe, 0xb2, 0xc4, 0x87,
|
0x45, 0x9c, 0x85, 0x68, 0xa4, 0xac, 0xf6, 0xad, 0xa2, 0x67, 0xc0, 0xb9, 0x73, 0x01, 0x8e, 0xd6,
|
||||||
0xb0, 0x97, 0x87, 0x49, 0x46, 0x4d, 0x80, 0x81, 0x69, 0x4e, 0xad, 0xf7, 0x68, 0xf8, 0x12, 0x1e,
|
0x77, 0xc1, 0x27, 0xa0, 0xf6, 0x0d, 0xcf, 0x4b, 0xfb, 0x8a, 0x10, 0x9e, 0x80, 0xfd, 0x2c, 0x88,
|
||||||
0x1b, 0xbb, 0x2a, 0xa0, 0x37, 0x19, 0x55, 0x1a, 0x3b, 0x60, 0x2f, 0x58, 0xa2, 0xa9, 0x54, 0x0e,
|
0x53, 0xac, 0x0d, 0xf4, 0x75, 0x72, 0x61, 0xbe, 0x37, 0x3a, 0x2f, 0xc1, 0xb1, 0x96, 0x2b, 0x7c,
|
||||||
0xaa, 0xbc, 0x35, 0xed, 0xf0, 0x0a, 0x9e, 0xdc, 0x73, 0x95, 0xe0, 0xa9, 0xa2, 0xf8, 0x1c, 0x6c,
|
0x7c, 0x97, 0x62, 0x21, 0xa1, 0x0d, 0xac, 0x29, 0x89, 0x25, 0xe6, 0xc2, 0x36, 0x94, 0xb6, 0x2a,
|
||||||
0x61, 0xa0, 0x8a, 0xdc, 0x1f, 0xbf, 0xda, 0x25, 0xa2, 0x3a, 0xf2, 0x66, 0xc4, 0xf8, 0x27, 0x82,
|
0xed, 0xdc, 0x82, 0xc7, 0xab, 0x5e, 0xc1, 0x68, 0x22, 0x30, 0xbc, 0x02, 0x16, 0xd3, 0x90, 0x6a,
|
||||||
0x47, 0x67, 0xeb, 0x54, 0x9c, 0x83, 0x5d, 0xaf, 0xc4, 0x6f, 0x77, 0x99, 0xdc, 0x5c, 0xe3, 0xbe,
|
0x6e, 0xf6, 0x5e, 0xed, 0x62, 0x51, 0x69, 0x79, 0x35, 0xa2, 0x83, 0xc0, 0xf1, 0x08, 0xf3, 0x0c,
|
||||||
0xdb, 0x51, 0x65, 0xee, 0x9a, 0x2c, 0x56, 0x77, 0x5e, 0xeb, 0xf7, 0x9d, 0xd7, 0xfa, 0x51, 0x78,
|
0xf3, 0xd5, 0xfc, 0xe7, 0xa0, 0x9e, 0xa6, 0x64, 0xa2, 0x6f, 0xe9, 0x1f, 0xe4, 0xcb, 0x56, 0xfd,
|
||||||
0x68, 0x55, 0x78, 0xe8, 0x57, 0xe1, 0xa1, 0x3f, 0x85, 0x87, 0xbe, 0x9c, 0xff, 0xdf, 0x5b, 0xfc,
|
0xe6, 0x66, 0x78, 0xe9, 0x2b, 0xb4, 0xf7, 0xdb, 0x00, 0x8f, 0x86, 0xeb, 0xa3, 0x61, 0x06, 0xac,
|
||||||
0xb0, 0x01, 0x7c, 0xb6, 0x66, 0xdd, 0xea, 0xf7, 0x7f, 0xf3, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xe6,
|
0x52, 0x22, 0x7c, 0xbb, 0x8b, 0x92, 0xea, 0x7a, 0xe7, 0xdd, 0x8e, 0xac, 0x52, 0xe7, 0x27, 0xd0,
|
||||||
0x72, 0xde, 0x35, 0xe4, 0x03, 0x00, 0x00,
|
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.
|
// 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
|
// Clients can use this to detect features and capabilities when using
|
||||||
// containerd.
|
// containerd.
|
||||||
Plugins(ctx context.Context, in *PluginsRequest, opts ...grpc.CallOption) (*PluginsResponse, error)
|
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 {
|
type introspectionClient struct {
|
||||||
@ -273,6 +320,15 @@ func (c *introspectionClient) Plugins(ctx context.Context, in *PluginsRequest, o
|
|||||||
return out, nil
|
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.
|
// IntrospectionServer is the server API for Introspection service.
|
||||||
type IntrospectionServer interface {
|
type IntrospectionServer interface {
|
||||||
// Plugins returns a list of plugins in containerd.
|
// 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
|
// Clients can use this to detect features and capabilities when using
|
||||||
// containerd.
|
// containerd.
|
||||||
Plugins(context.Context, *PluginsRequest) (*PluginsResponse, error)
|
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) {
|
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)
|
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{
|
var _Introspection_serviceDesc = grpc.ServiceDesc{
|
||||||
ServiceName: "containerd.services.introspection.v1.Introspection",
|
ServiceName: "containerd.services.introspection.v1.Introspection",
|
||||||
HandlerType: (*IntrospectionServer)(nil),
|
HandlerType: (*IntrospectionServer)(nil),
|
||||||
@ -312,6 +388,10 @@ var _Introspection_serviceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "Plugins",
|
MethodName: "Plugins",
|
||||||
Handler: _Introspection_Plugins_Handler,
|
Handler: _Introspection_Plugins_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Server",
|
||||||
|
Handler: _Introspection_Server_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "github.com/containerd/containerd/api/services/introspection/v1/introspection.proto",
|
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
|
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 {
|
func encodeVarintIntrospection(dAtA []byte, offset int, v uint64) int {
|
||||||
for v >= 1<<7 {
|
for v >= 1<<7 {
|
||||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||||
@ -583,6 +690,22 @@ func (m *PluginsResponse) Size() (n int) {
|
|||||||
return n
|
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) {
|
func sovIntrospection(x uint64) (n int) {
|
||||||
for {
|
for {
|
||||||
n++
|
n++
|
||||||
@ -645,6 +768,17 @@ func (this *PluginsResponse) String() string {
|
|||||||
}, "")
|
}, "")
|
||||||
return s
|
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 {
|
func valueToStringIntrospection(v interface{}) string {
|
||||||
rv := reflect.ValueOf(v)
|
rv := reflect.ValueOf(v)
|
||||||
if rv.IsNil() {
|
if rv.IsNil() {
|
||||||
@ -1206,6 +1340,92 @@ func (m *PluginsResponse) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
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) {
|
func skipIntrospection(dAtA []byte) (n int, err error) {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
|
@ -4,6 +4,7 @@ package containerd.services.introspection.v1;
|
|||||||
|
|
||||||
import "github.com/containerd/containerd/api/types/platform.proto";
|
import "github.com/containerd/containerd/api/types/platform.proto";
|
||||||
import "google/rpc/status.proto";
|
import "google/rpc/status.proto";
|
||||||
|
import "google/protobuf/empty.proto";
|
||||||
import weak "gogoproto/gogo.proto";
|
import weak "gogoproto/gogo.proto";
|
||||||
|
|
||||||
option go_package = "github.com/containerd/containerd/api/services/introspection/v1;introspection";
|
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
|
// Clients can use this to detect features and capabilities when using
|
||||||
// containerd.
|
// containerd.
|
||||||
rpc Plugins(PluginsRequest) returns (PluginsResponse);
|
rpc Plugins(PluginsRequest) returns (PluginsResponse);
|
||||||
|
// Server returns information about the containerd server
|
||||||
|
rpc Server(google.protobuf.Empty) returns (ServerResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
message Plugin {
|
message Plugin {
|
||||||
@ -79,3 +82,7 @@ message PluginsRequest {
|
|||||||
message PluginsResponse {
|
message PluginsResponse {
|
||||||
repeated Plugin plugins = 1 [(gogoproto.nullable) = false];
|
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
|
// List lists all active leases, returning the full list of
|
||||||
// leases and optionally including the referenced resources.
|
// leases and optionally including the referenced resources.
|
||||||
rpc List(ListRequest) returns (ListResponse);
|
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.
|
// Lease is an object which retains resources while it exists.
|
||||||
@ -62,3 +71,32 @@ message ListRequest {
|
|||||||
message ListResponse {
|
message ListResponse {
|
||||||
repeated Lease leases = 1;
|
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) {
|
func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) {
|
||||||
switch compression {
|
switch compression {
|
||||||
case Uncompressed:
|
case Uncompressed:
|
||||||
|
263
vendor/github.com/containerd/containerd/archive/tar.go
generated
vendored
263
vendor/github.com/containerd/containerd/archive/tar.go
generated
vendored
@ -19,9 +19,7 @@ package archive
|
|||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -91,11 +89,6 @@ const (
|
|||||||
// archives.
|
// archives.
|
||||||
whiteoutMetaPrefix = whiteoutPrefix + whiteoutPrefix
|
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
|
// whiteoutOpaqueDir file means directory has been made opaque - meaning
|
||||||
// readdir calls to this directory do not follow to lower layers.
|
// readdir calls to this directory do not follow to lower layers.
|
||||||
whiteoutOpaqueDir = whiteoutMetaPrefix + ".opq"
|
whiteoutOpaqueDir = whiteoutMetaPrefix + ".opq"
|
||||||
@ -117,11 +110,15 @@ func Apply(ctx context.Context, root string, r io.Reader, opts ...ApplyOpt) (int
|
|||||||
if options.Filter == nil {
|
if options.Filter == nil {
|
||||||
options.Filter = all
|
options.Filter = all
|
||||||
}
|
}
|
||||||
|
if options.applyFunc == nil {
|
||||||
return apply(ctx, root, tar.NewReader(r), options)
|
options.applyFunc = applyNaive
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyNaive applies a tar stream of an OCI style diff tar.
|
return options.applyFunc(ctx, root, tar.NewReader(r), options)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
// 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) {
|
func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
|
||||||
var (
|
var (
|
||||||
@ -131,11 +128,49 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
|
|||||||
// may occur out of order
|
// may occur out of order
|
||||||
unpackedPaths = make(map[string]struct{})
|
unpackedPaths = make(map[string]struct{})
|
||||||
|
|
||||||
// Used for aufs plink directory
|
convertWhiteout = options.ConvertWhiteout
|
||||||
aufsTempdir = ""
|
|
||||||
aufsHardlinks = make(map[string]*tar.Header)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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.
|
// Iterate through the files in the archive.
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -193,85 +228,21 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
|
|||||||
if base == "" {
|
if base == "" {
|
||||||
parentPath = filepath.Dir(path)
|
parentPath = filepath.Dir(path)
|
||||||
}
|
}
|
||||||
if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
|
if err := mkparent(ctx, parentPath, root, options.Parents); err != nil {
|
||||||
err = mkdirAll(parentPath, 0755)
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, errors.Wrapf(err, "failed to convert whiteout file %q", hdr.Name)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
return 0, err
|
|
||||||
}
|
}
|
||||||
|
if !writeFile {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// If path exits we almost always just want to remove and replace it.
|
// 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)
|
srcData := io.Reader(tr)
|
||||||
srcHdr := hdr
|
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 {
|
if err := createTarFile(ctx, path, root, srcHdr, srcData); err != nil {
|
||||||
return 0, err
|
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))
|
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 {
|
type changeWriter struct {
|
||||||
tw *tar.Writer
|
tw *tar.Writer
|
||||||
source string
|
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)))
|
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
|
name := p
|
||||||
if strings.HasPrefix(name, string(filepath.Separator)) {
|
if strings.HasPrefix(name, string(filepath.Separator)) {
|
||||||
name, err = filepath.Rel(string(filepath.Separator), name)
|
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 {
|
func (cw *changeWriter) includeParents(hdr *tar.Header) error {
|
||||||
|
if cw.addedDirs == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
name := strings.TrimRight(hdr.Name, "/")
|
name := strings.TrimRight(hdr.Name, "/")
|
||||||
fname := filepath.Join(cw.source, name)
|
fname := filepath.Join(cw.source, name)
|
||||||
parent := filepath.Dir(name)
|
parent := filepath.Dir(name)
|
||||||
@ -684,3 +704,26 @@ func hardlinkRootPath(root, linkname string) (string, error) {
|
|||||||
}
|
}
|
||||||
return targetPath, nil
|
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
|
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
|
// ApplyOpt allows setting mutable archive apply properties on creation
|
||||||
type ApplyOpt func(options *ApplyOptions) error
|
type ApplyOpt func(options *ApplyOptions) error
|
||||||
@ -24,6 +36,9 @@ type ApplyOpt func(options *ApplyOptions) error
|
|||||||
// Filter specific files from the archive
|
// Filter specific files from the archive
|
||||||
type Filter func(*tar.Header) (bool, error)
|
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
|
// all allows all files
|
||||||
func all(_ *tar.Header) (bool, error) {
|
func all(_ *tar.Header) (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
@ -36,3 +51,24 @@ func WithFilter(f Filter) ApplyOpt {
|
|||||||
return nil
|
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
|
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
|
// AsWindowsContainerLayer indicates that the tar stream to apply is that of
|
||||||
// a Windows Container Layer. The caller must be holding SeBackupPrivilege and
|
// a Windows Container Layer. The caller must be holding SeBackupPrivilege and
|
||||||
// SeRestorePrivilege.
|
// SeRestorePrivilege.
|
||||||
func AsWindowsContainerLayer() ApplyOpt {
|
func AsWindowsContainerLayer() ApplyOpt {
|
||||||
return func(options *ApplyOptions) error {
|
return func(options *ApplyOptions) error {
|
||||||
options.IsWindowsContainerLayer = true
|
options.applyFunc = applyWindowsLayer
|
||||||
return nil
|
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 (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"context"
|
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containerd/continuity/fs"
|
||||||
"github.com/containerd/continuity/sysx"
|
"github.com/containerd/continuity/sysx"
|
||||||
"github.com/opencontainers/runc/libcontainer/system"
|
"github.com/opencontainers/runc/libcontainer/system"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -74,10 +75,6 @@ func openFile(name string, flag int, perm os.FileMode) (*os.File, error) {
|
|||||||
return f, err
|
return f, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func mkdirAll(path string, perm os.FileMode) error {
|
|
||||||
return os.MkdirAll(path, perm)
|
|
||||||
}
|
|
||||||
|
|
||||||
func mkdir(path string, perm os.FileMode) error {
|
func mkdir(path string, perm os.FileMode) error {
|
||||||
if err := os.Mkdir(path, perm); err != nil {
|
if err := os.Mkdir(path, perm); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -149,11 +146,71 @@ func getxattr(path, attr string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setxattr(path, key, value string) 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.
|
func copyDirInfo(fi os.FileInfo, path string) error {
|
||||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
st := fi.Sys().(*syscall.Stat_t)
|
||||||
func apply(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
|
if err := os.Lchown(path, int(st.Uid), int(st.Gid)); err != nil {
|
||||||
return applyNaive(ctx, root, tr, options)
|
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"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -36,6 +35,7 @@ import (
|
|||||||
"github.com/Microsoft/go-winio"
|
"github.com/Microsoft/go-winio"
|
||||||
"github.com/Microsoft/hcsshim"
|
"github.com/Microsoft/hcsshim"
|
||||||
"github.com/containerd/containerd/sys"
|
"github.com/containerd/containerd/sys"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -107,10 +107,6 @@ func openFile(name string, flag int, perm os.FileMode) (*os.File, error) {
|
|||||||
return sys.OpenFileSequential(name, flag, perm)
|
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 {
|
func mkdir(path string, perm os.FileMode) error {
|
||||||
return os.Mkdir(path, perm)
|
return os.Mkdir(path, perm)
|
||||||
}
|
}
|
||||||
@ -153,16 +149,8 @@ func setxattr(path, key, value string) error {
|
|||||||
return errors.New("xattrs not supported on Windows")
|
return errors.New("xattrs not supported on Windows")
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply 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
|
||||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
// layer using the hcsshim layer writer and backup streams.
|
||||||
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.
|
|
||||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
// 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) {
|
func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
|
||||||
home, id := filepath.Split(root)
|
home, id := filepath.Split(root)
|
||||||
@ -170,7 +158,7 @@ func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options
|
|||||||
HomeDir: home,
|
HomeDir: home,
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := hcsshim.NewLayerWriter(info, id, options.ParentLayerPaths)
|
w, err := hcsshim.NewLayerWriter(info, id, options.Parents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
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())
|
utimes[1] = unix.NsecToTimespec(mtime.UnixNano())
|
||||||
|
|
||||||
if err := unix.UtimesNanoAt(unix.AT_FDCWD, path, utimes[0:], unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
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
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containerd/containerd/defaults"
|
"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
|
// BinaryIO forwards container STDOUT|STDERR directly to a logging binary
|
||||||
func BinaryIO(binary string, args map[string]string) Creator {
|
func BinaryIO(binary string, args map[string]string) Creator {
|
||||||
return func(_ string) (IO, error) {
|
return func(_ string) (IO, error) {
|
||||||
|
binary = filepath.Clean(binary)
|
||||||
|
if !strings.HasPrefix(binary, "/") {
|
||||||
|
return nil, errors.New("absolute path needed")
|
||||||
|
}
|
||||||
uri := &url.URL{
|
uri := &url.URL{
|
||||||
Scheme: "binary",
|
Scheme: "binary",
|
||||||
Host: binary,
|
Path: binary,
|
||||||
}
|
}
|
||||||
|
q := uri.Query()
|
||||||
for k, v := range args {
|
for k, v := range args {
|
||||||
uri.Query().Set(k, v)
|
q.Set(k, v)
|
||||||
}
|
}
|
||||||
|
uri.RawQuery = q.Encode()
|
||||||
|
res := uri.String()
|
||||||
return &logURI{
|
return &logURI{
|
||||||
config: Config{
|
config: Config{
|
||||||
Stdout: uri.String(),
|
Stdout: res,
|
||||||
Stderr: uri.String(),
|
Stderr: res,
|
||||||
},
|
},
|
||||||
}, nil
|
}, 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.
|
// If the log file already exists, the logs will be appended to the file.
|
||||||
func LogFile(path string) Creator {
|
func LogFile(path string) Creator {
|
||||||
return func(_ string) (IO, error) {
|
return func(_ string) (IO, error) {
|
||||||
|
path = filepath.Clean(path)
|
||||||
|
if !strings.HasPrefix(path, "/") {
|
||||||
|
return nil, errors.New("absolute path needed")
|
||||||
|
}
|
||||||
uri := &url.URL{
|
uri := &url.URL{
|
||||||
Scheme: "file",
|
Scheme: "file",
|
||||||
Host: path,
|
Path: path,
|
||||||
}
|
}
|
||||||
|
res := uri.String()
|
||||||
return &logURI{
|
return &logURI{
|
||||||
config: Config{
|
config: Config{
|
||||||
Stdout: uri.String(),
|
Stdout: res,
|
||||||
Stderr: uri.String(),
|
Stderr: res,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/containerd/containerd/cio/io_unix.go
generated
vendored
4
vendor/github.com/containerd/containerd/cio/io_unix.go
generated
vendored
@ -72,6 +72,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var wg = &sync.WaitGroup{}
|
var wg = &sync.WaitGroup{}
|
||||||
|
if fifos.Stdout != "" {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
p := bufPool.Get().(*[]byte)
|
p := bufPool.Get().(*[]byte)
|
||||||
@ -81,8 +82,9 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
|
|||||||
pipes.Stdout.Close()
|
pipes.Stdout.Close()
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
if !fifos.Terminal {
|
if !fifos.Terminal && fifos.Stderr != "" {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
p := bufPool.Get().(*[]byte)
|
p := bufPool.Get().(*[]byte)
|
||||||
|
155
vendor/github.com/containerd/containerd/client.go
generated
vendored
155
vendor/github.com/containerd/containerd/client.go
generated
vendored
@ -43,6 +43,7 @@ import (
|
|||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
contentproxy "github.com/containerd/containerd/content/proxy"
|
contentproxy "github.com/containerd/containerd/content/proxy"
|
||||||
"github.com/containerd/containerd/defaults"
|
"github.com/containerd/containerd/defaults"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/events"
|
"github.com/containerd/containerd/events"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/leases"
|
"github.com/containerd/containerd/leases"
|
||||||
@ -56,6 +57,7 @@ import (
|
|||||||
"github.com/containerd/containerd/snapshots"
|
"github.com/containerd/containerd/snapshots"
|
||||||
snproxy "github.com/containerd/containerd/snapshots/proxy"
|
snproxy "github.com/containerd/containerd/snapshots/proxy"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
|
"github.com/gogo/protobuf/types"
|
||||||
ptypes "github.com/gogo/protobuf/types"
|
ptypes "github.com/gogo/protobuf/types"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -86,13 +88,23 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
|
|||||||
if copts.timeout == 0 {
|
if copts.timeout == 0 {
|
||||||
copts.timeout = 10 * time.Second
|
copts.timeout = 10 * time.Second
|
||||||
}
|
}
|
||||||
rt := fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS)
|
|
||||||
if copts.defaultRuntime != "" {
|
|
||||||
rt = copts.defaultRuntime
|
|
||||||
}
|
|
||||||
c := &Client{
|
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 {
|
if copts.services != nil {
|
||||||
c.services = *copts.services
|
c.services = *copts.services
|
||||||
}
|
}
|
||||||
@ -102,7 +114,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
|
|||||||
grpc.WithInsecure(),
|
grpc.WithInsecure(),
|
||||||
grpc.FailOnNonTempDialError(true),
|
grpc.FailOnNonTempDialError(true),
|
||||||
grpc.WithBackoffMaxDelay(3 * time.Second),
|
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.
|
// TODO(stevvooe): We may need to allow configuration of this on the client.
|
||||||
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
|
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
|
||||||
@ -134,19 +146,15 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
|
|||||||
c.conn, c.connector = conn, connector
|
c.conn, c.connector = conn, connector
|
||||||
}
|
}
|
||||||
if copts.services == nil && c.conn == nil {
|
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
|
// check namespace labels for default runtime
|
||||||
if copts.defaultRuntime == "" && copts.defaultns != "" {
|
if copts.defaultRuntime == "" && c.defaultns != "" {
|
||||||
namespaces := c.NamespaceService()
|
if label, err := c.GetLabel(context.Background(), defaults.DefaultRuntimeNSLabel); err != nil {
|
||||||
ctx := context.Background()
|
|
||||||
if labels, err := namespaces.Labels(ctx, copts.defaultns); err == nil {
|
|
||||||
if defaultRuntime, ok := labels[defaults.DefaultRuntimeNSLabel]; ok {
|
|
||||||
c.runtime = defaultRuntime
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
|
} else if label != "" {
|
||||||
|
c.runtime = label
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,20 +171,17 @@ func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
c := &Client{
|
c := &Client{
|
||||||
|
defaultns: copts.defaultns,
|
||||||
conn: conn,
|
conn: conn,
|
||||||
runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
|
runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
|
||||||
}
|
}
|
||||||
|
|
||||||
// check namespace labels for default runtime
|
// check namespace labels for default runtime
|
||||||
if copts.defaultRuntime == "" && copts.defaultns != "" {
|
if copts.defaultRuntime == "" && c.defaultns != "" {
|
||||||
namespaces := c.NamespaceService()
|
if label, err := c.GetLabel(context.Background(), defaults.DefaultRuntimeNSLabel); err != nil {
|
||||||
ctx := context.Background()
|
|
||||||
if labels, err := namespaces.Labels(ctx, copts.defaultns); err == nil {
|
|
||||||
if defaultRuntime, ok := labels[defaults.DefaultRuntimeNSLabel]; ok {
|
|
||||||
c.runtime = defaultRuntime
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
|
} else if label != "" {
|
||||||
|
c.runtime = label
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,13 +198,15 @@ type Client struct {
|
|||||||
connMu sync.Mutex
|
connMu sync.Mutex
|
||||||
conn *grpc.ClientConn
|
conn *grpc.ClientConn
|
||||||
runtime string
|
runtime string
|
||||||
|
defaultns string
|
||||||
|
platform platforms.MatchComparer
|
||||||
connector func() (*grpc.ClientConn, error)
|
connector func() (*grpc.ClientConn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reconnect re-establishes the GRPC connection to the containerd daemon
|
// Reconnect re-establishes the GRPC connection to the containerd daemon
|
||||||
func (c *Client) Reconnect() error {
|
func (c *Client) Reconnect() error {
|
||||||
if c.connector == nil {
|
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()
|
c.connMu.Lock()
|
||||||
defer c.connMu.Unlock()
|
defer c.connMu.Unlock()
|
||||||
@ -222,10 +229,10 @@ func (c *Client) IsServing(ctx context.Context) (bool, error) {
|
|||||||
c.connMu.Lock()
|
c.connMu.Lock()
|
||||||
if c.conn == nil {
|
if c.conn == nil {
|
||||||
c.connMu.Unlock()
|
c.connMu.Unlock()
|
||||||
return false, errors.New("no grpc connection available")
|
return false, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection available")
|
||||||
}
|
}
|
||||||
c.connMu.Unlock()
|
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 {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -294,10 +301,14 @@ type RemoteContext struct {
|
|||||||
PlatformMatcher platforms.MatchComparer
|
PlatformMatcher platforms.MatchComparer
|
||||||
|
|
||||||
// Unpack is done after an image is pulled to extract into a snapshotter.
|
// 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
|
// If an image is not unpacked on pull, it can be unpacked any time
|
||||||
// afterwards. Unpacking is required to run an image.
|
// afterwards. Unpacking is required to run an image.
|
||||||
Unpack bool
|
Unpack bool
|
||||||
|
|
||||||
|
// UnpackOpts handles options to the unpack call.
|
||||||
|
UnpackOpts []UnpackOpt
|
||||||
|
|
||||||
// Snapshotter used for unpacking
|
// Snapshotter used for unpacking
|
||||||
Snapshotter string
|
Snapshotter string
|
||||||
|
|
||||||
@ -329,9 +340,8 @@ type RemoteContext struct {
|
|||||||
// MaxConcurrentDownloads is the max concurrent content downloads for each pull.
|
// MaxConcurrentDownloads is the max concurrent content downloads for each pull.
|
||||||
MaxConcurrentDownloads int
|
MaxConcurrentDownloads int
|
||||||
|
|
||||||
// AppendDistributionSourceLabel allows fetcher to add distribute source
|
// AllMetadata downloads all manifests and known-configuration files
|
||||||
// label for each blob content, which doesn't work for legacy schema1.
|
AllMetadata bool
|
||||||
AppendDistributionSourceLabel bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultRemoteContext() *RemoteContext {
|
func defaultRemoteContext() *RemoteContext {
|
||||||
@ -339,7 +349,6 @@ func defaultRemoteContext() *RemoteContext {
|
|||||||
Resolver: docker.NewResolver(docker.ResolverOptions{
|
Resolver: docker.NewResolver(docker.ResolverOptions{
|
||||||
Client: http.DefaultClient,
|
Client: http.DefaultClient,
|
||||||
}),
|
}),
|
||||||
Snapshotter: DefaultSnapshotter,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +363,7 @@ func (c *Client) Fetch(ctx context.Context, ref string, opts ...RemoteOpt) (imag
|
|||||||
}
|
}
|
||||||
|
|
||||||
if fetchCtx.Unpack {
|
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 {
|
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)
|
pusher, err := pushCtx.Resolver.Pusher(ctx, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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))
|
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.
|
// 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
|
// 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
|
// SnapshotService returns the underlying snapshotter for the provided snapshotter name
|
||||||
func (c *Client) SnapshotService(snapshotterName string) snapshots.Snapshotter {
|
func (c *Client) SnapshotService(snapshotterName string) snapshots.Snapshotter {
|
||||||
|
snapshotterName, err := c.resolveSnapshotterName(context.Background(), snapshotterName)
|
||||||
|
if err != nil {
|
||||||
|
snapshotterName = DefaultSnapshotter
|
||||||
|
}
|
||||||
if c.snapshotters != nil {
|
if c.snapshotters != nil {
|
||||||
return c.snapshotters[snapshotterName]
|
return c.snapshotters[snapshotterName]
|
||||||
}
|
}
|
||||||
@ -642,7 +681,7 @@ func (c *Client) Version(ctx context.Context) (Version, error) {
|
|||||||
c.connMu.Lock()
|
c.connMu.Lock()
|
||||||
if c.conn == nil {
|
if c.conn == nil {
|
||||||
c.connMu.Unlock()
|
c.connMu.Unlock()
|
||||||
return Version{}, errors.New("no grpc connection available")
|
return Version{}, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection available")
|
||||||
}
|
}
|
||||||
c.connMu.Unlock()
|
c.connMu.Unlock()
|
||||||
response, err := c.VersionService().Version(ctx, &ptypes.Empty{})
|
response, err := c.VersionService().Version(ctx, &ptypes.Empty{})
|
||||||
@ -655,6 +694,58 @@ func (c *Client) Version(ctx context.Context) (Version, error) {
|
|||||||
}, nil
|
}, 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
|
// CheckRuntime returns true if the current runtime matches the expected
|
||||||
// runtime. Providing various parts of the runtime schema will match those
|
// runtime. Providing various parts of the runtime schema will match those
|
||||||
// parts of the expected runtime
|
// parts of the expected runtime
|
||||||
|
16
vendor/github.com/containerd/containerd/client_opts.go
generated
vendored
16
vendor/github.com/containerd/containerd/client_opts.go
generated
vendored
@ -28,6 +28,7 @@ import (
|
|||||||
type clientOpts struct {
|
type clientOpts struct {
|
||||||
defaultns string
|
defaultns string
|
||||||
defaultRuntime string
|
defaultRuntime string
|
||||||
|
defaultPlatform platforms.MatchComparer
|
||||||
services *services
|
services *services
|
||||||
dialOptions []grpc.DialOption
|
dialOptions []grpc.DialOption
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
@ -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
|
// WithDialOpts allows grpc.DialOptions to be set on the connection
|
||||||
func WithDialOpts(opts []grpc.DialOption) ClientOpt {
|
func WithDialOpts(opts []grpc.DialOption) ClientOpt {
|
||||||
return func(c *clientOpts) error {
|
return func(c *clientOpts) error {
|
||||||
@ -195,11 +204,10 @@ func WithMaxConcurrentDownloads(max int) RemoteOpt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithAppendDistributionSourceLabel allows fetcher to add distribute source
|
// WithAllMetadata downloads all manifests and known-configuration files
|
||||||
// label for each blob content, which doesn't work for legacy schema1.
|
func WithAllMetadata() RemoteOpt {
|
||||||
func WithAppendDistributionSourceLabel() RemoteOpt {
|
|
||||||
return func(_ *Client, c *RemoteContext) error {
|
return func(_ *Client, c *RemoteContext) error {
|
||||||
c.AppendDistributionSourceLabel = true
|
c.AllMetadata = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
vendor/github.com/containerd/containerd/container.go
generated
vendored
33
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/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/api/types"
|
"github.com/containerd/containerd/api/types"
|
||||||
|
tasktypes "github.com/containerd/containerd/api/types/task"
|
||||||
"github.com/containerd/containerd/cio"
|
"github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
@ -49,7 +50,7 @@ type Container interface {
|
|||||||
// ID identifies the container
|
// ID identifies the container
|
||||||
ID() string
|
ID() string
|
||||||
// Info returns the underlying container record type
|
// 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 removes the container
|
||||||
Delete(context.Context, ...DeleteOpts) error
|
Delete(context.Context, ...DeleteOpts) error
|
||||||
// NewTask creates a new task based on the container metadata
|
// NewTask creates a new task based on the container metadata
|
||||||
@ -82,6 +83,7 @@ func containerFromRecord(client *Client, c containers.Container) *container {
|
|||||||
return &container{
|
return &container{
|
||||||
client: client,
|
client: client,
|
||||||
id: c.ID,
|
id: c.ID,
|
||||||
|
metadata: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +92,7 @@ var _ = (Container)(&container{})
|
|||||||
type container struct {
|
type container struct {
|
||||||
client *Client
|
client *Client
|
||||||
id string
|
id string
|
||||||
|
metadata containers.Container
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns the container's unique id
|
// ID returns the container's unique id
|
||||||
@ -97,8 +100,22 @@ func (c *container) ID() string {
|
|||||||
return c.id
|
return c.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *container) Info(ctx context.Context) (containers.Container, error) {
|
func (c *container) Info(ctx context.Context, opts ...InfoOpts) (containers.Container, error) {
|
||||||
return c.get(ctx)
|
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) {
|
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
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -362,7 +383,9 @@ func (c *container) loadTask(ctx context.Context, ioAttach cio.Attach) (Task, er
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var i cio.IO
|
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 {
|
if i, err = attachExistingIO(response, ioAttach); err != nil {
|
||||||
return nil, err
|
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"
|
"context"
|
||||||
|
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/defaults"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
"github.com/containerd/containerd/snapshots"
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
"github.com/gogo/protobuf/types"
|
"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
|
// UpdateContainerOpts allows the caller to set additional options when updating a container
|
||||||
type UpdateContainerOpts func(ctx context.Context, client *Client, c *containers.Container) error
|
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
|
// WithRuntime allows a user to specify the runtime name and additional options that should
|
||||||
// be used to create tasks for the container
|
// be used to create tasks for the container
|
||||||
func WithRuntime(name string, options interface{}) NewContainerOpts {
|
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
|
// WithContainerLabels adds the provided labels to the container
|
||||||
func WithContainerLabels(labels map[string]string) NewContainerOpts {
|
func WithContainerLabels(labels map[string]string) NewContainerOpts {
|
||||||
return func(_ context.Context, _ *Client, c *containers.Container) error {
|
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
|
// WithSnapshot uses an existing root filesystem for the container
|
||||||
func WithSnapshot(id string) NewContainerOpts {
|
func WithSnapshot(id string) NewContainerOpts {
|
||||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
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
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
c.SnapshotKey = id
|
c.SnapshotKey = id
|
||||||
@ -123,13 +145,21 @@ func WithSnapshot(id string) NewContainerOpts {
|
|||||||
// root filesystem in read-write mode
|
// root filesystem in read-write mode
|
||||||
func WithNewSnapshot(id string, i Image, opts ...snapshots.Opt) NewContainerOpts {
|
func WithNewSnapshot(id string, i Image, opts ...snapshots.Opt) NewContainerOpts {
|
||||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
setSnapshotterIfEmpty(ctx, client, c)
|
|
||||||
parent := identity.ChainID(diffIDs).String()
|
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
|
return err
|
||||||
}
|
}
|
||||||
c.SnapshotKey = id
|
c.SnapshotKey = id
|
||||||
@ -144,7 +174,13 @@ func WithSnapshotCleanup(ctx context.Context, client *Client, c containers.Conta
|
|||||||
if c.Snapshotter == "" {
|
if c.Snapshotter == "" {
|
||||||
return errors.Wrapf(errdefs.ErrInvalidArgument, "container.Snapshotter must be set to cleanup rootfs snapshot")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -153,13 +189,21 @@ func WithSnapshotCleanup(ctx context.Context, client *Client, c containers.Conta
|
|||||||
// root filesystem in read-only mode
|
// root filesystem in read-only mode
|
||||||
func WithNewSnapshotView(id string, i Image, opts ...snapshots.Opt) NewContainerOpts {
|
func WithNewSnapshotView(id string, i Image, opts ...snapshots.Opt) NewContainerOpts {
|
||||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
setSnapshotterIfEmpty(ctx, client, c)
|
|
||||||
parent := identity.ChainID(diffIDs).String()
|
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
|
return err
|
||||||
}
|
}
|
||||||
c.SnapshotKey = id
|
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.
|
// WithContainerExtension appends extension data to the container object.
|
||||||
// Use this to decorate the container object with additional data for the client
|
// Use this to decorate the container object with additional data for the client
|
||||||
// integration.
|
// integration.
|
||||||
@ -235,3 +264,8 @@ func WithSpec(s *oci.Spec, opts ...oci.SpecOpts) NewContainerOpts {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithoutRefreshedMetadata will use the current metadata attached to the container object
|
||||||
|
func WithoutRefreshedMetadata(i *InfoConfig) {
|
||||||
|
i.Refresh = false
|
||||||
|
}
|
||||||
|
14
vendor/github.com/containerd/containerd/container_opts_unix.go
generated
vendored
14
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/containers"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
"github.com/opencontainers/image-spec/identity"
|
"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 {
|
func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool) NewContainerOpts {
|
||||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
setSnapshotterIfEmpty(ctx, client, c)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
snapshotter = client.SnapshotService(c.Snapshotter)
|
|
||||||
parent = identity.ChainID(diffIDs).String()
|
parent = identity.ChainID(diffIDs).String()
|
||||||
usernsID = fmt.Sprintf("%s-%d-%d", parent, uid, gid)
|
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.Stat(ctx, usernsID); err == nil {
|
||||||
if _, err := snapshotter.Prepare(ctx, id, usernsID); err == nil {
|
if _, err := snapshotter.Prepare(ctx, id, usernsID); err == nil {
|
||||||
c.SnapshotKey = id
|
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/containers"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
ptypes "github.com/gogo/protobuf/types"
|
ptypes "github.com/gogo/protobuf/types"
|
||||||
"github.com/opencontainers/image-spec/identity"
|
"github.com/opencontainers/image-spec/identity"
|
||||||
@ -58,7 +57,7 @@ func WithRestoreImage(ctx context.Context, id string, client *Client, checkpoint
|
|||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
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]
|
[Unit]
|
||||||
Description=containerd container runtime
|
Description=containerd container runtime
|
||||||
Documentation=https://containerd.io
|
Documentation=https://containerd.io
|
||||||
After=network.target
|
After=network.target local-fs.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStartPre=-/sbin/modprobe overlay
|
ExecStartPre=-/sbin/modprobe overlay
|
||||||
@ -9,6 +9,7 @@ ExecStart=/usr/local/bin/containerd
|
|||||||
|
|
||||||
Delegate=yes
|
Delegate=yes
|
||||||
KillMode=process
|
KillMode=process
|
||||||
|
Restart=always
|
||||||
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||||
# in the kernel. We recommend using cgroups to do container-local accounting.
|
# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||||
LimitNPROC=infinity
|
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.
|
// This property is required and immutable.
|
||||||
Runtime RuntimeInfo
|
Runtime RuntimeInfo
|
||||||
|
|
||||||
// Spec should carry the the runtime specification used to implement the
|
// Spec should carry the runtime specification used to implement the
|
||||||
// container.
|
// container.
|
||||||
//
|
//
|
||||||
// This field is required but mutable.
|
// 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())
|
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
|
return p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,6 +169,28 @@ func CopyReaderAt(cw Writer, ra ReaderAt, n int64) error {
|
|||||||
return err
|
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
|
// seekReader attempts to seek the reader to the given offset, either by
|
||||||
// resolving `io.Seeker`, by detecting `io.ReaderAt`, or discarding
|
// resolving `io.Seeker`, by detecting `io.ReaderAt`, or discarding
|
||||||
// up to the given offset.
|
// 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/containerd/containerd/log"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/containerd/continuity"
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -661,6 +660,19 @@ func writeTimestampFile(p string, t time.Time) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return atomicWrite(p, b, 0666)
|
||||||
return continuity.AtomicWriteFile(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
|
// DefaultMaxSendMsgSize defines the default maximum message size for
|
||||||
// sending protobufs passed over the GRPC API.
|
// sending protobufs passed over the GRPC API.
|
||||||
DefaultMaxSendMsgSize = 16 << 20
|
DefaultMaxSendMsgSize = 16 << 20
|
||||||
// DefaultRuntimeNSLabel defines the namespace label to check for
|
// DefaultRuntimeNSLabel defines the namespace label to check for the
|
||||||
// default runtime
|
// default runtime
|
||||||
DefaultRuntimeNSLabel = "containerd.io/defaults/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
|
// default snapshotter
|
||||||
DefaultSnapshotterNSLabel = "containerd.io/defaults/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
|
// DefaultFIFODir is the default location used by client-side cio library
|
||||||
// to store FIFOs.
|
// to store FIFOs.
|
||||||
DefaultFIFODir = "/run/containerd/fifo"
|
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
|
// DefaultFIFODir is the default location used by client-side cio library
|
||||||
// to store FIFOs. Unused on Windows.
|
// to store FIFOs. Unused on Windows.
|
||||||
DefaultFIFODir = ""
|
DefaultFIFODir = ""
|
||||||
|
// DefaultRuntime is the default windows runtime
|
||||||
|
DefaultRuntime = "io.containerd.runhcs.v1"
|
||||||
)
|
)
|
||||||
|
11
vendor/github.com/containerd/containerd/diff.go
generated
vendored
11
vendor/github.com/containerd/containerd/diff.go
generated
vendored
@ -45,10 +45,17 @@ type diffRemote struct {
|
|||||||
client diffapi.DiffClient
|
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{
|
req := &diffapi.ApplyRequest{
|
||||||
Diff: fromDescriptor(diff),
|
Diff: fromDescriptor(desc),
|
||||||
Mounts: fromMounts(mounts),
|
Mounts: fromMounts(mounts),
|
||||||
|
Payloads: config.ProcessorPayloads,
|
||||||
}
|
}
|
||||||
resp, err := r.client.Apply(ctx, req)
|
resp, err := r.client.Apply(ctx, req)
|
||||||
if err != nil {
|
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"
|
"context"
|
||||||
|
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/gogo/protobuf/types"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
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)
|
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
|
// Applier allows applying diffs between mounts
|
||||||
type Applier interface {
|
type Applier interface {
|
||||||
// Apply applies the content referred to by the given descriptor to
|
// 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
|
// implementation and content descriptor. For example, in the common
|
||||||
// case the descriptor is a file system difference in tar format,
|
// case the descriptor is a file system difference in tar format,
|
||||||
// that tar would be applied on top of the mounts.
|
// 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
|
// 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
|
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.
|
// client-side errors to the correct types.
|
||||||
package errdefs
|
package errdefs
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
// Definitions of common error types used throughout containerd. All containerd
|
// Definitions of common error types used throughout containerd. All containerd
|
||||||
// errors returned by most packages will map into one of these errors classes.
|
// 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 {
|
func IsNotImplemented(err error) bool {
|
||||||
return errors.Cause(err) == ErrNotImplemented
|
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
|
package errdefs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -55,6 +56,10 @@ func ToGRPC(err error) error {
|
|||||||
return status.Errorf(codes.Unavailable, err.Error())
|
return status.Errorf(codes.Unavailable, err.Error())
|
||||||
case IsNotImplemented(err):
|
case IsNotImplemented(err):
|
||||||
return status.Errorf(codes.Unimplemented, err.Error())
|
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
|
return err
|
||||||
@ -89,6 +94,10 @@ func FromGRPC(err error) error {
|
|||||||
cls = ErrFailedPrecondition
|
cls = ErrFailedPrecondition
|
||||||
case codes.Unimplemented:
|
case codes.Unimplemented:
|
||||||
cls = ErrNotImplemented
|
cls = ErrNotImplemented
|
||||||
|
case codes.Canceled:
|
||||||
|
cls = context.Canceled
|
||||||
|
case codes.DeadlineExceeded:
|
||||||
|
cls = context.DeadlineExceeded
|
||||||
default:
|
default:
|
||||||
cls = ErrUnknown
|
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.Forwarder = &Exchange{}
|
||||||
var _ events.Subscriber = &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
|
// This is useful when an event is forwarded on behalf of another namespace or
|
||||||
// when the event is propagated on behalf of another publisher.
|
// 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"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/containerd/containerd/images/oci"
|
"github.com/containerd/containerd/images/archive"
|
||||||
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Export exports an image to a Tar stream.
|
// Export exports images to a Tar stream.
|
||||||
// OCI format is used by default.
|
// The tar archive is in OCI format with a Docker compatible manifest
|
||||||
// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc.
|
// when a single target platform is given.
|
||||||
// TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream.
|
func (c *Client) Export(ctx context.Context, w io.Writer, opts ...archive.ExportOpt) error {
|
||||||
func (c *Client) Export(ctx context.Context, desc ocispec.Descriptor, opts ...oci.V1ExporterOpt) (io.ReadCloser, error) {
|
return archive.Export(ctx, c.ContentStore(), w, opts...)
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/diff"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/containerd/containerd/rootfs"
|
"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"
|
"github.com/opencontainers/image-spec/identity"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sync/semaphore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Image describes an image used by containers
|
// Image describes an image used by containers
|
||||||
@ -40,11 +45,13 @@ type Image interface {
|
|||||||
// Labels of the image
|
// Labels of the image
|
||||||
Labels() map[string]string
|
Labels() map[string]string
|
||||||
// Unpack unpacks the image's content into a snapshot
|
// 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 returns the unpacked diffids that make up images rootfs.
|
||||||
RootFS(ctx context.Context) ([]digest.Digest, error)
|
RootFS(ctx context.Context) ([]digest.Digest, error)
|
||||||
// Size returns the total size of the image's packed resources.
|
// Size returns the total size of the image's packed resources.
|
||||||
Size(ctx context.Context) (int64, error)
|
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 descriptor for the image.
|
||||||
Config(ctx context.Context) (ocispec.Descriptor, error)
|
Config(ctx context.Context) (ocispec.Descriptor, error)
|
||||||
// IsUnpacked returns whether or not an image is unpacked.
|
// IsUnpacked returns whether or not an image is unpacked.
|
||||||
@ -53,6 +60,49 @@ type Image interface {
|
|||||||
ContentStore() content.Store
|
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{})
|
var _ = (Image)(&image{})
|
||||||
|
|
||||||
// NewImage returns a client image object from the metadata 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{
|
return &image{
|
||||||
client: client,
|
client: client,
|
||||||
i: i,
|
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) {
|
func (i *image) Size(ctx context.Context) (int64, error) {
|
||||||
provider := i.client.ContentStore()
|
return i.Usage(ctx, WithUsageManifestLimit(1), WithManifestUsage())
|
||||||
return i.i.Size(ctx, provider, i.platform)
|
}
|
||||||
|
|
||||||
|
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) {
|
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) {
|
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()
|
cs := i.client.ContentStore()
|
||||||
|
|
||||||
diffs, err := i.i.RootFS(ctx, cs, i.platform)
|
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
|
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)
|
ctx, done, err := i.client.WithLease(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer done(ctx)
|
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)
|
layers, err := i.getLayers(ctx, i.platform)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
sn = i.client.SnapshotService(snapshotterName)
|
|
||||||
a = i.client.DiffService()
|
a = i.client.DiffService()
|
||||||
cs = i.client.ContentStore()
|
cs = i.client.ContentStore()
|
||||||
|
|
||||||
chain []digest.Digest
|
chain []digest.Digest
|
||||||
unpacked bool
|
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 {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,10 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package devices
|
package images
|
||||||
|
|
||||||
import (
|
const (
|
||||||
"os"
|
// AnnotationImageName is an annotation on a Descriptor in an index.json
|
||||||
|
// containing the `Name` value as used by an `Image` struct
|
||||||
"github.com/pkg/errors"
|
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
|
||||||
|
}
|
148
vendor/github.com/containerd/containerd/images/archive/importer.go
generated
vendored
148
vendor/github.com/containerd/containerd/images/archive/importer.go
generated
vendored
@ -22,12 +22,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/containerd/containerd/archive/compression"
|
"github.com/containerd/containerd/archive/compression"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
@ -36,6 +38,22 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"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
|
// ImportIndex imports an index from a tar archive image bundle
|
||||||
// - implements Docker v1.1, v1.2 and OCI v1.
|
// - implements Docker v1.1, v1.2 and OCI v1.
|
||||||
// - prefers OCI v1 when provided
|
// - prefers OCI v1 when provided
|
||||||
@ -43,8 +61,7 @@ import (
|
|||||||
// - normalizes Docker references and adds as OCI ref name
|
// - normalizes Docker references and adds as OCI ref name
|
||||||
// e.g. alpine:latest -> docker.io/library/alpine:latest
|
// e.g. alpine:latest -> docker.io/library/alpine:latest
|
||||||
// - existing OCI reference names are untouched
|
// - 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, opts ...ImportOpt) (ocispec.Descriptor, error) {
|
||||||
func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (ocispec.Descriptor, error) {
|
|
||||||
var (
|
var (
|
||||||
tr = tar.NewReader(reader)
|
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)
|
symlinks = make(map[string]string)
|
||||||
blobs = make(map[string]ocispec.Descriptor)
|
blobs = make(map[string]ocispec.Descriptor)
|
||||||
|
iopts importOpts
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
if err := o(&iopts); err != nil {
|
||||||
|
return ocispec.Descriptor{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
hdr, err := tr.Next()
|
hdr, err := tr.Next()
|
||||||
if err == io.EOF {
|
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.
|
// 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.
|
// as Docker v1.1 or v1.2.
|
||||||
if ociLayout.Version != "" {
|
if ociLayout.Version != "" {
|
||||||
if ociLayout.Version != ocispec.ImageLayoutVersion {
|
if ociLayout.Version != ocispec.ImageLayoutVersion {
|
||||||
@ -137,17 +162,21 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (oc
|
|||||||
if !ok {
|
if !ok {
|
||||||
return ocispec.Descriptor{}, errors.Errorf("image config %q not found", mfst.Config)
|
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 {
|
if err != nil {
|
||||||
return ocispec.Descriptor{}, errors.Wrap(err, "failed to resolve layers")
|
return ocispec.Descriptor{}, errors.Wrap(err, "failed to resolve layers")
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest := ocispec.Manifest{
|
manifest := struct {
|
||||||
Versioned: specs.Versioned{
|
SchemaVersion int `json:"schemaVersion"`
|
||||||
|
MediaType string `json:"mediaType"`
|
||||||
|
Config ocispec.Descriptor `json:"config"`
|
||||||
|
Layers []ocispec.Descriptor `json:"layers"`
|
||||||
|
}{
|
||||||
SchemaVersion: 2,
|
SchemaVersion: 2,
|
||||||
},
|
MediaType: images.MediaTypeDockerSchema2Manifest,
|
||||||
Config: config,
|
Config: config,
|
||||||
Layers: layers,
|
Layers: layers,
|
||||||
}
|
}
|
||||||
@ -181,7 +210,8 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (oc
|
|||||||
}
|
}
|
||||||
|
|
||||||
mfstdesc.Annotations = map[string]string{
|
mfstdesc.Annotations = map[string]string{
|
||||||
ocispec.AnnotationRefName: normalized,
|
images.AnnotationImageName: normalized,
|
||||||
|
ocispec.AnnotationRefName: ociReferenceName(normalized),
|
||||||
}
|
}
|
||||||
|
|
||||||
idx.Manifests = append(idx.Manifests, mfstdesc)
|
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
|
return dgstr.Digest(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveLayers(ctx context.Context, store content.Store, layerFiles []string, blobs map[string]ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
func resolveLayers(ctx context.Context, store content.Store, layerFiles []string, blobs map[string]ocispec.Descriptor, compress bool) ([]ocispec.Descriptor, error) {
|
||||||
var layers []ocispec.Descriptor
|
layers := make([]ocispec.Descriptor, len(layerFiles))
|
||||||
for _, f := range layerFiles {
|
descs := map[digest.Digest]*ocispec.Descriptor{}
|
||||||
|
filters := []string{}
|
||||||
|
for i, f := range layerFiles {
|
||||||
desc, ok := blobs[f]
|
desc, ok := blobs[f]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.Errorf("layer %q not found", f)
|
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
|
// Open blob, resolve media type
|
||||||
ra, err := store.ReaderAt(ctx, desc)
|
ra, err := store.ReaderAt(ctx, desc)
|
||||||
if err != nil {
|
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))
|
s, err := compression.DecompressStream(content.NewReader(ra))
|
||||||
if err != nil {
|
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 {
|
if s.GetCompression() == compression.Uncompressed {
|
||||||
// TODO: Support compressing and writing back to content store
|
if compress {
|
||||||
desc.MediaType = ocispec.MediaTypeImageLayer
|
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 {
|
} else {
|
||||||
desc.MediaType = ocispec.MediaTypeImageLayerGzip
|
layers[i].MediaType = images.MediaTypeDockerSchema2Layer
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
layers[i].MediaType = images.MediaTypeDockerSchema2LayerGzip
|
||||||
}
|
}
|
||||||
s.Close()
|
s.Close()
|
||||||
|
|
||||||
layers = append(layers, desc)
|
|
||||||
}
|
}
|
||||||
return layers, nil
|
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) {
|
func writeManifest(ctx context.Context, cs content.Ingester, manifest interface{}, mediaType string) (ocispec.Descriptor, error) {
|
||||||
manifestBytes, err := json.Marshal(manifest)
|
manifestBytes, err := json.Marshal(manifest)
|
||||||
if err != nil {
|
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 (
|
import (
|
||||||
"strings"
|
"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/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -69,7 +70,7 @@ func isImagePrefix(s, prefix string) bool {
|
|||||||
|
|
||||||
func normalizeReference(ref string) (string, error) {
|
func normalizeReference(ref string) (string, error) {
|
||||||
// TODO: Replace this function to not depend on reference package
|
// TODO: Replace this function to not depend on reference package
|
||||||
normalized, err := reference.ParseDockerRef(ref)
|
normalized, err := distref.ParseDockerRef(ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrapf(err, "normalize image ref %q", ref)
|
return "", errors.Wrapf(err, "normalize image ref %q", ref)
|
||||||
}
|
}
|
||||||
@ -77,6 +78,31 @@ func normalizeReference(ref string) (string, error) {
|
|||||||
return normalized.String(), nil
|
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
|
// DigestTranslator creates a digest reference by adding the
|
||||||
// digest to an image name
|
// digest to an image name
|
||||||
func DigestTranslator(prefix string) func(digest.Digest) string {
|
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.
|
// 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 {
|
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 {
|
for _, desc := range descs {
|
||||||
desc := desc
|
desc := desc
|
||||||
|
|
||||||
@ -126,10 +126,11 @@ func Dispatch(ctx context.Context, handler Handler, limiter *semaphore.Weighted,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
desc := desc
|
desc := desc
|
||||||
|
|
||||||
children, err := handler.Handle(ctx, desc)
|
children, err := handler.Handle(ctx2, desc)
|
||||||
if limiter != nil {
|
if limiter != nil {
|
||||||
limiter.Release(1)
|
limiter.Release(1)
|
||||||
}
|
}
|
||||||
@ -141,7 +142,7 @@ func Dispatch(ctx context.Context, handler Handler, limiter *semaphore.Weighted,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(children) > 0 {
|
if len(children) > 0 {
|
||||||
return Dispatch(ctx, handler, limiter, children...)
|
return Dispatch(ctx2, handler, limiter, children...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
58
vendor/github.com/containerd/containerd/images/image.go
generated
vendored
58
vendor/github.com/containerd/containerd/images/image.go
generated
vendored
@ -20,7 +20,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
@ -119,7 +118,7 @@ func (image *Image) Size(ctx context.Context, provider content.Provider, platfor
|
|||||||
}
|
}
|
||||||
size += desc.Size
|
size += desc.Size
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}), FilterPlatforms(ChildrenHandler(provider), platform)), image.Target)
|
}), LimitManifests(FilterPlatforms(ChildrenHandler(provider), platform), platform, 1)), image.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
type platformManifest struct {
|
type platformManifest struct {
|
||||||
@ -142,6 +141,7 @@ type platformManifest struct {
|
|||||||
// this direction because this abstraction is not needed.`
|
// 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) {
|
func Manifest(ctx context.Context, provider content.Provider, image ocispec.Descriptor, platform platforms.MatchComparer) (ocispec.Manifest, error) {
|
||||||
var (
|
var (
|
||||||
|
limit = 1
|
||||||
m []platformManifest
|
m []platformManifest
|
||||||
wasIndex bool
|
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
|
wasIndex = true
|
||||||
|
|
||||||
|
if len(descs) > limit {
|
||||||
|
return descs[:limit], nil
|
||||||
|
}
|
||||||
return descs, nil
|
return descs, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "unexpected media type %v for %v", desc.MediaType, desc.Digest)
|
return nil, errors.Wrapf(errdefs.ErrNotFound, "unexpected media type %v for %v", desc.MediaType, desc.Digest)
|
||||||
}), image); err != nil {
|
}), image); err != nil {
|
||||||
@ -227,17 +239,6 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
|
|||||||
}
|
}
|
||||||
return ocispec.Manifest{}, err
|
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
|
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...)
|
descs = append(descs, index.Manifests...)
|
||||||
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
|
default:
|
||||||
MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip,
|
if IsLayerType(desc.MediaType) || IsKnownConfig(desc.MediaType) {
|
||||||
MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig,
|
|
||||||
ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip,
|
|
||||||
ocispec.MediaTypeImageLayerNonDistributable, ocispec.MediaTypeImageLayerNonDistributableGzip,
|
|
||||||
MediaTypeContainerd1Checkpoint, MediaTypeContainerd1CheckpointConfig:
|
|
||||||
// childless data types.
|
// childless data types.
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
}
|
||||||
log.G(ctx).Warnf("encountered unknown type %v; children may not be fetched", desc.MediaType)
|
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
|
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
|
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.
|
// mediatype definitions for image components handled in containerd.
|
||||||
//
|
//
|
||||||
// oci components are generally referenced directly, although we may centralize
|
// oci components are generally referenced directly, although we may centralize
|
||||||
@ -40,3 +49,78 @@ const (
|
|||||||
// Legacy Docker schema1 manifest
|
// Legacy Docker schema1 manifest
|
||||||
MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
|
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
|
|
||||||
}
|
|
45
vendor/github.com/containerd/containerd/import.go
generated
vendored
45
vendor/github.com/containerd/containerd/import.go
generated
vendored
@ -35,6 +35,7 @@ type importOpts struct {
|
|||||||
imageRefT func(string) string
|
imageRefT func(string) string
|
||||||
dgstRefT func(digest.Digest) string
|
dgstRefT func(digest.Digest) string
|
||||||
allPlatforms bool
|
allPlatforms bool
|
||||||
|
compress bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportOpt allows the caller to specify import specific options
|
// 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.
|
// Import imports an image from a Tar stream using reader.
|
||||||
// Caller needs to specify importer. Future version may use oci.v1 as the default.
|
// 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) {
|
func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt) ([]images.Image, error) {
|
||||||
var iopts importOpts
|
var iopts importOpts
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@ -91,7 +101,12 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
|
|||||||
}
|
}
|
||||||
defer done(ctx)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -110,7 +125,7 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
|
|||||||
}
|
}
|
||||||
var platformMatcher = platforms.All
|
var platformMatcher = platforms.All
|
||||||
if !iopts.allPlatforms {
|
if !iopts.allPlatforms {
|
||||||
platformMatcher = platforms.Default()
|
platformMatcher = c.platform
|
||||||
}
|
}
|
||||||
|
|
||||||
var handler images.HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
var handler images.HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||||
@ -130,17 +145,13 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range idx.Manifests {
|
for _, m := range idx.Manifests {
|
||||||
if ref := m.Annotations[ocispec.AnnotationRefName]; ref != "" {
|
name := imageName(m.Annotations, iopts.imageRefT)
|
||||||
if iopts.imageRefT != nil {
|
if name != "" {
|
||||||
ref = iopts.imageRefT(ref)
|
|
||||||
}
|
|
||||||
if ref != "" {
|
|
||||||
imgs = append(imgs, images.Image{
|
imgs = append(imgs, images.Image{
|
||||||
Name: ref,
|
Name: name,
|
||||||
Target: m,
|
Target: m,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if iopts.dgstRefT != nil {
|
if iopts.dgstRefT != nil {
|
||||||
ref := iopts.dgstRefT(m.Digest)
|
ref := iopts.dgstRefT(m.Digest)
|
||||||
if ref != "" {
|
if ref != "" {
|
||||||
@ -178,3 +189,17 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
|
|||||||
|
|
||||||
return imgs, nil
|
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/archive/compression"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
|
|||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
cs = image.ContentStore()
|
cs = image.ContentStore()
|
||||||
platform = platforms.Default()
|
platform = c.platform
|
||||||
)
|
)
|
||||||
manifest, err := images.Manifest(ctx, cs, image.Target(), platform)
|
manifest, err := images.Manifest(ctx, cs, image.Target(), platform)
|
||||||
if err != nil {
|
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
|
// 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)
|
_, ok := leases.FromContext(ctx)
|
||||||
if ok {
|
if ok {
|
||||||
return ctx, func(context.Context) error {
|
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()
|
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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
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)
|
Create(context.Context, ...Opt) (Lease, error)
|
||||||
Delete(context.Context, Lease, ...DeleteOpt) error
|
Delete(context.Context, Lease, ...DeleteOpt) error
|
||||||
List(context.Context, ...string) ([]Lease, 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
|
// Lease retains resources to prevent cleanup before
|
||||||
@ -42,6 +45,13 @@ type Lease struct {
|
|||||||
Labels map[string]string
|
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
|
// DeleteOptions provide options on image delete
|
||||||
type DeleteOptions struct {
|
type DeleteOptions struct {
|
||||||
Synchronous bool
|
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
|
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.
|
// messages.
|
||||||
G = GetLogger
|
G = GetLogger
|
||||||
|
|
||||||
// L is an alias for the the standard logger.
|
// L is an alias for the standard logger.
|
||||||
L = logrus.NewEntry(logrus.StandardLogger())
|
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
|
return namespaces, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteNamespaces) Delete(ctx context.Context, namespace string) error {
|
func (r *remoteNamespaces) Delete(ctx context.Context, namespace string, opts ...namespaces.DeleteOpts) error {
|
||||||
var req api.DeleteNamespaceRequest
|
i := namespaces.DeleteInfo{
|
||||||
|
Name: namespace,
|
||||||
req.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)
|
_, err := r.client.Delete(ctx, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errdefs.FromGRPC(err)
|
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
|
// WithNamespace sets a given namespace on the context
|
||||||
func WithNamespace(ctx context.Context, namespace string) context.Context {
|
func WithNamespace(ctx context.Context, namespace string) context.Context {
|
||||||
ctx = context.WithValue(ctx, namespaceKey{}, namespace) // set our key for namespace
|
ctx = context.WithValue(ctx, namespaceKey{}, namespace) // set our key for namespace
|
||||||
|
// also store on the grpc and ttrpc headers so it gets picked up by any clients that
|
||||||
// also store on the grpc headers so it gets picked up by any clients that
|
|
||||||
// are using this.
|
// are using this.
|
||||||
return withGRPCNamespaceHeader(ctx, namespace)
|
return withTTRPCNamespaceHeader(withGRPCNamespaceHeader(ctx, namespace), namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamespaceFromEnv uses the namespace defined in CONTAINERD_NAMESPACE or
|
// 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) {
|
func Namespace(ctx context.Context) (string, bool) {
|
||||||
namespace, ok := ctx.Value(namespaceKey{}).(string)
|
namespace, ok := ctx.Value(namespaceKey{}).(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fromGRPCHeader(ctx)
|
if namespace, ok = fromGRPCHeader(ctx); !ok {
|
||||||
|
return fromTTRPCHeader(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return namespace, ok
|
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) {
|
func NamespaceRequired(ctx context.Context) (string, error) {
|
||||||
namespace, ok := Namespace(ctx)
|
namespace, ok := Namespace(ctx)
|
||||||
if !ok || namespace == "" {
|
if !ok || namespace == "" {
|
||||||
return "", errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace is required")
|
return "", errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Validate(namespace); err != nil {
|
if err := Validate(namespace); err != nil {
|
||||||
return "", errors.Wrap(err, "namespace validation")
|
return "", errors.Wrap(err, "namespace validation")
|
||||||
}
|
}
|
||||||
|
|
||||||
return namespace, nil
|
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)
|
List(ctx context.Context) ([]string, error)
|
||||||
|
|
||||||
// Delete removes the namespace. The namespace must be empty to be deleted.
|
// 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
|
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.
|
// context, client and container instance.
|
||||||
func ApplyOpts(ctx context.Context, client Client, c *containers.Container, s *Spec, opts ...SpecOpts) error {
|
func ApplyOpts(ctx context.Context, client Client, c *containers.Container, s *Spec, opts ...SpecOpts) error {
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@ -141,7 +141,6 @@ func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error {
|
|||||||
Path: defaultRootfsPath,
|
Path: defaultRootfsPath,
|
||||||
},
|
},
|
||||||
Process: &specs.Process{
|
Process: &specs.Process{
|
||||||
Env: defaultUnixEnv,
|
|
||||||
Cwd: "/",
|
Cwd: "/",
|
||||||
NoNewPrivileges: true,
|
NoNewPrivileges: true,
|
||||||
User: specs.User{
|
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
|
package oci
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"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
|
// setCapabilities sets Linux Capabilities to empty if unset
|
||||||
func setCapabilities(s *Spec) {
|
func setCapabilities(s *Spec) {
|
||||||
setProcess(s)
|
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 {
|
func WithSpecFromBytes(p []byte) SpecOpts {
|
||||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||||
*s = Spec{} // make sure spec is cleared.
|
*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
|
// replaceOrAppendEnvValues returns the defaults with the overrides either
|
||||||
// replaced by env key or appended to the list
|
// replaced by env key or appended to the list
|
||||||
func replaceOrAppendEnvValues(defaults, overrides []string) []string {
|
func replaceOrAppendEnvValues(defaults, overrides []string) []string {
|
||||||
@ -312,7 +334,11 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts {
|
|||||||
|
|
||||||
setProcess(s)
|
setProcess(s)
|
||||||
if s.Linux != nil {
|
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
|
cmd := config.Cmd
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
cmd = args
|
cmd = args
|
||||||
@ -334,7 +360,7 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts {
|
|||||||
// even if there is no specified user in the image config
|
// even if there is no specified user in the image config
|
||||||
return WithAdditionalGIDs("root")(ctx, client, c, s)
|
return WithAdditionalGIDs("root")(ctx, client, c, s)
|
||||||
} else if s.Windows != nil {
|
} 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
|
cmd := config.Cmd
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
cmd = args
|
cmd = args
|
||||||
@ -607,7 +633,7 @@ func WithUserID(uid uint32) SpecOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithUsername sets the correct UID and GID for the container
|
// 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,
|
// does not exist, or the username is not found in /etc/passwd,
|
||||||
// it returns error.
|
// it returns error.
|
||||||
func WithUsername(username string) SpecOpts {
|
func WithUsername(username string) SpecOpts {
|
||||||
@ -980,6 +1006,21 @@ func WithParentCgroupDevices(_ context.Context, _ Client, _ *containers.Containe
|
|||||||
return nil
|
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
|
// WithDefaultUnixDevices adds the default devices for unix such as /dev/null, /dev/random to
|
||||||
// the container's resource cgroup spec
|
// the container's resource cgroup spec
|
||||||
func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
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
|
// WithPrivileged sets up options for a privileged container
|
||||||
// TODO(justincormack) device handling
|
|
||||||
var WithPrivileged = Compose(
|
var WithPrivileged = Compose(
|
||||||
WithAllCapabilities,
|
WithAllCapabilities,
|
||||||
WithMaskedPaths(nil),
|
WithMaskedPaths(nil),
|
||||||
@ -1139,3 +1179,85 @@ func WithAnnotations(annotations map[string]string) SpecOpts {
|
|||||||
return nil
|
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"
|
"github.com/containerd/containerd/containers"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WithWindowsCPUCount sets the `Windows.Resources.CPU.Count` section to the
|
// WithWindowsCPUCount sets the `Windows.Resources.CPU.Count` section to the
|
||||||
@ -65,3 +66,14 @@ func WithWindowNetworksAllowUnqualifiedDNSQuery() SpecOpts {
|
|||||||
return nil
|
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
|
package dialer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -28,8 +29,19 @@ type dialResult struct {
|
|||||||
err error
|
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
|
// 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 (
|
var (
|
||||||
stopC = make(chan struct{})
|
stopC = make(chan struct{})
|
||||||
synC = make(chan *dialResult)
|
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
|
// Only returns a match comparer for a single platform
|
||||||
// using default resolution logic for the 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 ARMv7, will also match ARMv6 and ARMv5
|
||||||
// For ARMv6, will also match ARMv5
|
// For ARMv6, will also match ARMv5
|
||||||
func Only(platform specs.Platform) MatchComparer {
|
func Only(platform specs.Platform) MatchComparer {
|
||||||
platform = Normalize(platform)
|
platform = Normalize(platform)
|
||||||
if platform.Architecture == "arm" {
|
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" {
|
if platform.Variant == "v7" {
|
||||||
return orderedPlatformComparer{
|
return orderedPlatformComparer{
|
||||||
matchers: []Matcher{
|
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 {
|
switch variant {
|
||||||
case "8":
|
case "8", "AArch64":
|
||||||
variant = "v8"
|
variant = "v8"
|
||||||
case "7", "7M", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)":
|
case "7", "7M", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)":
|
||||||
variant = "v7"
|
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"
|
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
|
// We use switch statements because they are slightly faster than map lookups
|
||||||
// and use a little less memory.
|
// 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.
|
// The OS value should be normalized before calling this function.
|
||||||
func isKnownOS(os string) bool {
|
func isKnownOS(os string) bool {
|
||||||
switch os {
|
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 true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -60,7 +60,7 @@ func isArmArch(arch string) bool {
|
|||||||
// The arch value should be normalized before being passed to this function.
|
// The arch value should be normalized before being passed to this function.
|
||||||
func isKnownArch(arch string) bool {
|
func isKnownArch(arch string) bool {
|
||||||
switch arch {
|
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 true
|
||||||
}
|
}
|
||||||
return false
|
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,
|
// specification. The returned matcher only looks for equality based on os,
|
||||||
// architecture and variant.
|
// 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.
|
// functionality.
|
||||||
//
|
//
|
||||||
// Applications should opt to use `Match` over directly parsing specifiers.
|
// Applications should opt to use `Match` over directly parsing specifiers.
|
||||||
|
1
vendor/github.com/containerd/containerd/plugin/context.go
generated
vendored
1
vendor/github.com/containerd/containerd/plugin/context.go
generated
vendored
@ -33,6 +33,7 @@ type InitContext struct {
|
|||||||
State string
|
State string
|
||||||
Config interface{}
|
Config interface{}
|
||||||
Address string
|
Address string
|
||||||
|
TTRPCAddress string
|
||||||
Events *exchange.Exchange
|
Events *exchange.Exchange
|
||||||
|
|
||||||
Meta *Meta // plugins can fill in metadata at init.
|
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")
|
ErrNoType = errors.New("plugin: no type")
|
||||||
// ErrNoPluginID is returned when no id is specified
|
// ErrNoPluginID is returned when no id is specified
|
||||||
ErrNoPluginID = errors.New("plugin: no id")
|
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,
|
// 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
|
// this allows the plugin loader differentiate between a plugin which is configured
|
||||||
// not to load and one that fails to load.
|
// 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
|
// context are passed in. The init function may modify the registration to
|
||||||
// add exports, capabilities and platform support declarations.
|
// add exports, capabilities and platform support declarations.
|
||||||
InitFn func(*InitContext) (interface{}, error)
|
InitFn func(*InitContext) (interface{}, error)
|
||||||
|
// Disable the plugin from loading
|
||||||
|
Disable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the registered plugin
|
// Init the registered plugin
|
||||||
@ -157,12 +160,16 @@ func Load(path string) (err error) {
|
|||||||
func Register(r *Registration) {
|
func Register(r *Registration) {
|
||||||
register.Lock()
|
register.Lock()
|
||||||
defer register.Unlock()
|
defer register.Unlock()
|
||||||
|
|
||||||
if r.Type == "" {
|
if r.Type == "" {
|
||||||
panic(ErrNoType)
|
panic(ErrNoType)
|
||||||
}
|
}
|
||||||
if r.ID == "" {
|
if r.ID == "" {
|
||||||
panic(ErrNoPluginID)
|
panic(ErrNoPluginID)
|
||||||
}
|
}
|
||||||
|
if err := checkUnique(r); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
var last bool
|
var last bool
|
||||||
for _, requires := range r.Requires {
|
for _, requires := range r.Requires {
|
||||||
@ -177,24 +184,36 @@ func Register(r *Registration) {
|
|||||||
register.r = append(register.r, r)
|
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.
|
// Graph returns an ordered list of registered plugins for initialization.
|
||||||
// Plugins in disableList specified by id will be disabled.
|
// Plugins in disableList specified by id will be disabled.
|
||||||
func Graph(disableList []string) (ordered []*Registration) {
|
func Graph(filter DisableFilter) (ordered []*Registration) {
|
||||||
register.RLock()
|
register.RLock()
|
||||||
defer register.RUnlock()
|
defer register.RUnlock()
|
||||||
for _, d := range disableList {
|
|
||||||
for i, r := range register.r {
|
for _, r := range register.r {
|
||||||
if r.ID == d {
|
if filter(r) {
|
||||||
register.r = append(register.r[:i], register.r[i+1:]...)
|
r.Disable = true
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
added := map[*Registration]bool{}
|
added := map[*Registration]bool{}
|
||||||
for _, r := range register.r {
|
for _, r := range register.r {
|
||||||
|
if r.Disable {
|
||||||
children(r.ID, r.Requires, added, &ordered)
|
continue
|
||||||
|
}
|
||||||
|
children(r, added, &ordered)
|
||||||
if !added[r] {
|
if !added[r] {
|
||||||
ordered = append(ordered, r)
|
ordered = append(ordered, r)
|
||||||
added[r] = true
|
added[r] = true
|
||||||
@ -203,11 +222,13 @@ func Graph(disableList []string) (ordered []*Registration) {
|
|||||||
return ordered
|
return ordered
|
||||||
}
|
}
|
||||||
|
|
||||||
func children(id string, types []Type, added map[*Registration]bool, ordered *[]*Registration) {
|
func children(reg *Registration, added map[*Registration]bool, ordered *[]*Registration) {
|
||||||
for _, t := range types {
|
for _, t := range reg.Requires {
|
||||||
for _, r := range register.r {
|
for _, r := range register.r {
|
||||||
if r.ID != id && (t == "*" || r.Type == t) {
|
if !r.Disable &&
|
||||||
children(r.ID, r.Requires, added, ordered)
|
r.URI() != reg.URI() &&
|
||||||
|
(t == "*" || r.Type == t) {
|
||||||
|
children(r, added, ordered)
|
||||||
if !added[r] {
|
if !added[r] {
|
||||||
*ordered = append(*ordered, r)
|
*ordered = append(*ordered, r)
|
||||||
added[r] = true
|
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)
|
Wait(context.Context) (<-chan ExitStatus, error)
|
||||||
// CloseIO allows various pipes to be closed on the process
|
// CloseIO allows various pipes to be closed on the process
|
||||||
CloseIO(context.Context, ...IOCloserOpts) error
|
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
|
Resize(ctx context.Context, w, h uint32) error
|
||||||
// IO returns the io set for the process
|
// IO returns the io set for the process
|
||||||
IO() cio.IO
|
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
|
// It is used by `Wait()` to return either a process exit code or an error
|
||||||
type ExitStatus struct {
|
type ExitStatus struct {
|
||||||
code uint32
|
code uint32
|
||||||
|
55
vendor/github.com/containerd/containerd/pull.go
generated
vendored
55
vendor/github.com/containerd/containerd/pull.go
generated
vendored
@ -32,7 +32,7 @@ import (
|
|||||||
|
|
||||||
// Pull downloads the provided content into containerd's content store
|
// Pull downloads the provided content into containerd's content store
|
||||||
// and returns a platform specific image object
|
// 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()
|
pullCtx := defaultRemoteContext()
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
if err := o(c, pullCtx); err != nil {
|
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 {
|
if len(pullCtx.Platforms) > 1 {
|
||||||
return nil, errors.New("cannot pull multiplatform image locally, try Fetch")
|
return nil, errors.New("cannot pull multiplatform image locally, try Fetch")
|
||||||
} else if len(pullCtx.Platforms) == 0 {
|
} else if len(pullCtx.Platforms) == 0 {
|
||||||
pullCtx.PlatformMatcher = platforms.Default()
|
pullCtx.PlatformMatcher = c.platform
|
||||||
} else {
|
} else {
|
||||||
p, err := platforms.Parse(pullCtx.Platforms[0])
|
p, err := platforms.Parse(pullCtx.Platforms[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -61,6 +61,30 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
|||||||
}
|
}
|
||||||
defer done(ctx)
|
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)
|
img, err := c.fetch(ctx, pullCtx, ref, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -69,10 +93,14 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
|||||||
i := NewImageWithPlatform(c, img, pullCtx.PlatformMatcher)
|
i := NewImageWithPlatform(c, img, pullCtx.PlatformMatcher)
|
||||||
|
|
||||||
if pullCtx.Unpack {
|
if pullCtx.Unpack {
|
||||||
if err := i.Unpack(ctx, pullCtx.Snapshotter); err != nil {
|
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)
|
return nil, errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
@ -112,9 +140,14 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
|
|||||||
childrenHandler := images.ChildrenHandler(store)
|
childrenHandler := images.ChildrenHandler(store)
|
||||||
// Set any children labels for that content
|
// Set any children labels for that content
|
||||||
childrenHandler = images.SetChildrenLabels(store, childrenHandler)
|
childrenHandler = images.SetChildrenLabels(store, childrenHandler)
|
||||||
|
if rCtx.AllMetadata {
|
||||||
// Filter manifests by platforms but allow to handle manifest
|
// Filter manifests by platforms but allow to handle manifest
|
||||||
// and configuration for not-target platforms
|
// and configuration for not-target platforms
|
||||||
childrenHandler = remotes.FilterManifestByPlatformHandler(childrenHandler, rCtx.PlatformMatcher)
|
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
|
// Sort and limit manifests if a finite number is needed
|
||||||
if limit > 0 {
|
if limit > 0 {
|
||||||
childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit)
|
childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit)
|
||||||
@ -131,21 +164,17 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
handlers := append(rCtx.BaseHandlers,
|
|
||||||
remotes.FetchHandler(store, fetcher),
|
|
||||||
convertibleHandler,
|
|
||||||
childrenHandler,
|
|
||||||
)
|
|
||||||
|
|
||||||
// append distribution source label to blob data
|
|
||||||
if rCtx.AppendDistributionSourceLabel {
|
|
||||||
appendDistSrcLabelHandler, err := docker.AppendDistributionSourceLabel(store, ref)
|
appendDistSrcLabelHandler, err := docker.AppendDistributionSourceLabel(store, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return images.Image{}, err
|
return images.Image{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
handlers = append(handlers, appendDistSrcLabelHandler)
|
handlers := append(rCtx.BaseHandlers,
|
||||||
}
|
remotes.FetchHandler(store, fetcher),
|
||||||
|
convertibleHandler,
|
||||||
|
childrenHandler,
|
||||||
|
appendDistSrcLabelHandler,
|
||||||
|
)
|
||||||
|
|
||||||
handler = images.Handlers(handlers...)
|
handler = images.Handlers(handlers...)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
299
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
299
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
@ -40,126 +40,278 @@ type dockerAuthorizer struct {
|
|||||||
credentials func(string) (string, string, error)
|
credentials func(string) (string, string, error)
|
||||||
|
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
header http.Header
|
||||||
mu sync.Mutex
|
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
|
// NewAuthorizer creates a Docker authorizer using the provided function to
|
||||||
// get credentials for the token server or basic auth.
|
// get credentials for the token server or basic auth.
|
||||||
|
// Deprecated: Use NewDockerAuthorizer
|
||||||
func NewAuthorizer(client *http.Client, f func(string) (string, string, error)) Authorizer {
|
func NewAuthorizer(client *http.Client, f func(string) (string, string, error)) Authorizer {
|
||||||
if client == nil {
|
return NewDockerAuthorizer(WithAuthClient(client), WithAuthCreds(f))
|
||||||
client = http.DefaultClient
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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{
|
return &dockerAuthorizer{
|
||||||
credentials: f,
|
credentials: ao.credentials,
|
||||||
client: client,
|
client: ao.client,
|
||||||
auth: map[string]string{},
|
header: ao.header,
|
||||||
|
handlers: make(map[string]*authHandler),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Authorize handles auth request.
|
||||||
func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
|
func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
|
||||||
// TODO: Lookup matching challenge and scope rather than just host
|
// skip if there is no auth handler
|
||||||
if auth := a.getAuth(req.URL.Host); auth != "" {
|
ah := a.getAuthHandler(req.URL.Host)
|
||||||
req.Header.Set("Authorization", auth)
|
if ah == nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auth, err := ah.authorize(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Authorization", auth)
|
||||||
return nil
|
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 {
|
func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.Response) error {
|
||||||
last := responses[len(responses)-1]
|
last := responses[len(responses)-1]
|
||||||
host := last.Request.URL.Host
|
host := last.Request.URL.Host
|
||||||
|
|
||||||
|
a.mu.Lock()
|
||||||
|
defer a.mu.Unlock()
|
||||||
for _, c := range parseAuthHeader(last.Header) {
|
for _, c := range parseAuthHeader(last.Header) {
|
||||||
if c.scheme == bearerAuth {
|
if c.scheme == bearerAuth {
|
||||||
if err := invalidAuthorization(c, responses); err != nil {
|
if err := invalidAuthorization(c, responses); err != nil {
|
||||||
// TODO: Clear token
|
delete(a.handlers, host)
|
||||||
a.setAuth(host, "")
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dmcg): Store challenge, not token
|
// reuse existing handler
|
||||||
// Move token fetching to authorize
|
//
|
||||||
return a.setTokenAuth(ctx, host, c.parameters)
|
// 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 {
|
} else if c.scheme == basicAuth && a.credentials != nil {
|
||||||
// TODO: Resolve credentials on authorize
|
|
||||||
username, secret, err := a.credentials(host)
|
username, secret, err := a.credentials(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if username != "" && secret != "" {
|
if username != "" && secret != "" {
|
||||||
auth := username + ":" + secret
|
common := tokenOptions{
|
||||||
a.setAuth(host, fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(auth))))
|
username: username,
|
||||||
|
secret: secret,
|
||||||
|
}
|
||||||
|
|
||||||
|
a.handlers[host] = newAuthHandler(a.client, a.header, c.scheme, common)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
|
return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *dockerAuthorizer) getAuth(host string) string {
|
func (a *dockerAuthorizer) generateTokenOptions(ctx context.Context, host string, c challenge) (tokenOptions, error) {
|
||||||
a.mu.Lock()
|
realm, ok := c.parameters["realm"]
|
||||||
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"]
|
|
||||||
if !ok {
|
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)
|
realmURL, err := url.Parse(realm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "invalid token auth challenge realm")
|
return tokenOptions{}, errors.Wrap(err, "invalid token auth challenge realm")
|
||||||
}
|
}
|
||||||
|
|
||||||
to := tokenOptions{
|
to := tokenOptions{
|
||||||
realm: realmURL.String(),
|
realm: realmURL.String(),
|
||||||
service: params["service"],
|
service: c.parameters["service"],
|
||||||
}
|
}
|
||||||
|
|
||||||
to.scopes = getTokenScopes(ctx, params)
|
scope, ok := c.parameters["scope"]
|
||||||
if len(to.scopes) == 0 {
|
if !ok {
|
||||||
return errors.Errorf("no scope specified for token auth challenge")
|
return tokenOptions{}, errors.Errorf("no scope specified for token auth challenge")
|
||||||
}
|
}
|
||||||
|
to.scopes = append(to.scopes, scope)
|
||||||
|
|
||||||
if a.credentials != nil {
|
if a.credentials != nil {
|
||||||
to.username, to.secret, err = a.credentials(host)
|
to.username, to.secret, err = a.credentials(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return tokenOptions{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var token string
|
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 != "" {
|
if to.secret != "" {
|
||||||
// Credential information is provided, use oauth POST endpoint
|
// credential information is provided, use oauth POST endpoint
|
||||||
token, err = a.fetchTokenWithOAuth(ctx, to)
|
token, err = ah.fetchTokenWithOAuth(ctx, to)
|
||||||
if err != nil {
|
err = errors.Wrap(err, "failed to fetch oauth token")
|
||||||
return errors.Wrap(err, "failed to fetch oauth token")
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Do request anonymously
|
// do request anonymously
|
||||||
token, err = a.fetchToken(ctx, to)
|
token, err = ah.fetchToken(ctx, to)
|
||||||
if err != nil {
|
err = errors.Wrap(err, "failed to fetch anonymous token")
|
||||||
return errors.Wrap(err, "failed to fetch anonymous token")
|
|
||||||
}
|
}
|
||||||
}
|
token = fmt.Sprintf("Bearer %s", token)
|
||||||
a.setAuth(host, fmt.Sprintf("Bearer %s", token))
|
|
||||||
|
|
||||||
return nil
|
r.token, r.err = token, err
|
||||||
|
r.Done()
|
||||||
|
return r.token, r.err
|
||||||
}
|
}
|
||||||
|
|
||||||
type tokenOptions struct {
|
type tokenOptions struct {
|
||||||
@ -178,7 +330,7 @@ type postTokenResponse struct {
|
|||||||
Scope string `json:"scope"`
|
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 := url.Values{}
|
||||||
form.Set("scope", strings.Join(to.scopes, " "))
|
form.Set("scope", strings.Join(to.scopes, " "))
|
||||||
form.Set("service", to.service)
|
form.Set("service", to.service)
|
||||||
@ -194,11 +346,18 @@ func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOpti
|
|||||||
form.Set("password", to.secret)
|
form.Set("password", to.secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := ctxhttp.Post(
|
req, err := http.NewRequest("POST", to.realm, strings.NewReader(form.Encode()))
|
||||||
ctx, a.client, to.realm,
|
if err != nil {
|
||||||
"application/x-www-form-urlencoded; charset=utf-8",
|
return "", err
|
||||||
strings.NewReader(form.Encode()),
|
}
|
||||||
)
|
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 {
|
if err != nil {
|
||||||
return "", err
|
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 September 2017, GCR is known to return 404.
|
||||||
// As of February 2018, JFrog Artifactory is known to return 401.
|
// As of February 2018, JFrog Artifactory is known to return 401.
|
||||||
if (resp.StatusCode == 405 && to.username != "") || resp.StatusCode == 404 || resp.StatusCode == 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 {
|
} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||||
b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
||||||
log.G(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithFields(logrus.Fields{
|
||||||
@ -237,13 +396,19 @@ type getTokenResponse struct {
|
|||||||
RefreshToken string `json:"refresh_token"`
|
RefreshToken string `json:"refresh_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// getToken fetches a token using a GET request
|
// fetchToken fetches a token using a GET request
|
||||||
func (a *dockerAuthorizer) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
|
func (ah *authHandler) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
|
||||||
req, err := http.NewRequest("GET", to.realm, nil)
|
req, err := http.NewRequest("GET", to.realm, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ah.header != nil {
|
||||||
|
for k, v := range ah.header {
|
||||||
|
req.Header[k] = append(req.Header[k], v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reqParams := req.URL.Query()
|
reqParams := req.URL.Query()
|
||||||
|
|
||||||
if to.service != "" {
|
if to.service != "" {
|
||||||
@ -260,7 +425,7 @@ func (a *dockerAuthorizer) fetchToken(ctx context.Context, to tokenOptions) (str
|
|||||||
|
|
||||||
req.URL.RawQuery = reqParams.Encode()
|
req.URL.RawQuery = reqParams.Encode()
|
||||||
|
|
||||||
resp, err := ctxhttp.Do(ctx, a.client, req)
|
resp, err := ctxhttp.Do(ctx, ah.client, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
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"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/docker/distribution/registry/api/errcode"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type dockerFetcher struct {
|
type dockerFetcher struct {
|
||||||
@ -40,26 +38,46 @@ type dockerFetcher struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) {
|
func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) {
|
||||||
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(
|
ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", desc.Digest))
|
||||||
logrus.Fields{
|
|
||||||
"base": r.base.String(),
|
|
||||||
"digest": desc.Digest,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
|
|
||||||
urls, err := r.getV2URLPaths(ctx, desc)
|
hosts := r.filterHosts(HostCapabilityPull)
|
||||||
if err != nil {
|
if len(hosts) == 0 {
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return newHTTPReadSeeker(desc.Size, func(offset int64) (io.ReadCloser, error) {
|
return newHTTPReadSeeker(desc.Size, func(offset int64) (io.ReadCloser, error) {
|
||||||
for _, u := range urls {
|
// firstly try fetch via external urls
|
||||||
rc, err := r.open(ctx, u, desc.MediaType, offset)
|
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 err != nil {
|
||||||
if errdefs.IsNotFound(err) {
|
if errdefs.IsNotFound(err) {
|
||||||
continue // try one of the other urls.
|
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
|
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,
|
return nil, errors.Wrapf(errdefs.ErrNotFound,
|
||||||
"could not fetch content descriptor %v (%v) from remote",
|
"could not fetch content descriptor %v (%v) from remote",
|
||||||
desc.Digest, desc.MediaType)
|
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) {
|
func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, offset int64) (io.ReadCloser, error) {
|
||||||
req, err := http.NewRequest(http.MethodGet, u, nil)
|
req.header.Set("Accept", strings.Join([]string{mediatype, `*/*`}, ", "))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Accept", strings.Join([]string{mediatype, `*`}, ", "))
|
|
||||||
|
|
||||||
if offset > 0 {
|
if offset > 0 {
|
||||||
// Note: "Accept-Ranges: bytes" cannot be trusted as some endpoints
|
// Note: "Accept-Ranges: bytes" cannot be trusted as some endpoints
|
||||||
// will return the header without supporting the range. The content
|
// will return the header without supporting the range. The content
|
||||||
// range must always be checked.
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -106,13 +157,13 @@ func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode == http.StatusNotFound {
|
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 {
|
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 {
|
if offset > 0 {
|
||||||
cr := resp.Header.Get("content-range")
|
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
|
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 {
|
func distributionSourceLabelKey(source string) string {
|
||||||
return fmt.Sprintf("%s.%s", labelDistributionSource, source)
|
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
|
||||||
|
}
|
||||||
|
185
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
185
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
@ -21,7 +21,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ import (
|
|||||||
|
|
||||||
type dockerPusher struct {
|
type dockerPusher struct {
|
||||||
*dockerBase
|
*dockerBase
|
||||||
tag string
|
object string
|
||||||
|
|
||||||
// TODO: namespace tracker
|
// TODO: namespace tracker
|
||||||
tracker StatusTracker
|
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")
|
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 (
|
var (
|
||||||
isManifest bool
|
isManifest bool
|
||||||
existCheck string
|
existCheck []string
|
||||||
|
host = hosts[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
switch desc.MediaType {
|
switch desc.MediaType {
|
||||||
case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList,
|
case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList,
|
||||||
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
|
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
|
||||||
isManifest = true
|
isManifest = true
|
||||||
if p.tag == "" {
|
existCheck = getManifestPath(p.object, desc.Digest)
|
||||||
existCheck = path.Join("manifests", desc.Digest.String())
|
|
||||||
} else {
|
|
||||||
existCheck = path.Join("manifests", p.tag)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
existCheck = path.Join("blobs", desc.Digest.String())
|
existCheck = []string{"blobs", desc.Digest.String()}
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodHead, p.url(existCheck), nil)
|
req := p.request(host, http.MethodHead, existCheck...)
|
||||||
if err != nil {
|
req.header.Set("Accept", strings.Join([]string{desc.MediaType, `*/*`}, ", "))
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Accept", strings.Join([]string{desc.MediaType, `*`}, ", "))
|
log.G(ctx).WithField("url", req.String()).Debugf("checking and pushing to")
|
||||||
resp, err := p.doRequestWithRetries(ctx, req, nil)
|
|
||||||
|
resp, err := req.doWithRetries(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) != ErrInvalidAuthorization {
|
if errors.Cause(err) != ErrInvalidAuthorization {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -92,7 +93,7 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
|||||||
} else {
|
} else {
|
||||||
if resp.StatusCode == http.StatusOK {
|
if resp.StatusCode == http.StatusOK {
|
||||||
var exists bool
|
var exists bool
|
||||||
if isManifest && p.tag != "" {
|
if isManifest && existCheck[1] != desc.Digest.String() {
|
||||||
dgstHeader := digest.Digest(resp.Header.Get("Docker-Content-Digest"))
|
dgstHeader := digest.Digest(resp.Header.Get("Docker-Content-Digest"))
|
||||||
if dgstHeader == desc.Digest {
|
if dgstHeader == desc.Digest {
|
||||||
exists = true
|
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 {
|
if isManifest {
|
||||||
var putPath string
|
putPath := getManifestPath(p.object, desc.Digest)
|
||||||
if p.tag != "" {
|
req = p.request(host, http.MethodPut, putPath...)
|
||||||
putPath = path.Join("manifests", p.tag)
|
req.header.Add("Content-Type", desc.MediaType)
|
||||||
} else {
|
} 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)
|
|
||||||
} else {
|
|
||||||
// TODO: Do monolithic upload if size is small
|
|
||||||
|
|
||||||
// Start upload request
|
// Start upload request
|
||||||
req, err = http.NewRequest(http.MethodPost, p.url("blobs", "uploads")+"/", nil)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := p.doRequestWithRetries(ctx, req, nil)
|
if resp.StatusCode == http.StatusUnauthorized {
|
||||||
|
log.G(ctx).Debugf("failed to mount from repository %s", fromRepo)
|
||||||
|
|
||||||
|
resp.Body.Close()
|
||||||
|
resp = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp == nil {
|
||||||
|
resp, err = req.doWithRetries(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case http.StatusOK, http.StatusAccepted, http.StatusNoContent:
|
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:
|
default:
|
||||||
// TODO: log error
|
// TODO: log error
|
||||||
return nil, errors.Errorf("unexpected response: %s", resp.Status)
|
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
|
// Support paths without host in location
|
||||||
if strings.HasPrefix(location, "/") {
|
if strings.HasPrefix(location, "/") {
|
||||||
// Support location string containing path and query
|
lurl, err = url.Parse(lhost.Scheme + "://" + lhost.Host + location)
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err = http.NewRequest(http.MethodPut, location, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
||||||
}
|
}
|
||||||
q := req.URL.Query()
|
|
||||||
q.Add("digest", desc.Digest.String())
|
|
||||||
req.URL.RawQuery = q.Encode()
|
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q := lurl.Query()
|
||||||
|
q.Add("digest", desc.Digest.String())
|
||||||
|
|
||||||
|
req = p.request(lhost, http.MethodPut)
|
||||||
|
req.path = lurl.Path + "?" + q.Encode()
|
||||||
}
|
}
|
||||||
p.tracker.SetStatus(ref, Status{
|
p.tracker.SetStatus(ref, Status{
|
||||||
Status: content.Status{
|
Status: content.Status{
|
||||||
@ -191,13 +219,22 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
|||||||
|
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
respC := make(chan *http.Response, 1)
|
respC := make(chan *http.Response, 1)
|
||||||
|
body := ioutil.NopCloser(pr)
|
||||||
|
|
||||||
req.Body = ioutil.NopCloser(pr)
|
req.body = func() (io.ReadCloser, error) {
|
||||||
req.ContentLength = desc.Size
|
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() {
|
go func() {
|
||||||
defer close(respC)
|
defer close(respC)
|
||||||
resp, err = p.doRequest(ctx, req)
|
resp, err = req.do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pr.CloseWithError(err)
|
pr.CloseWithError(err)
|
||||||
return
|
return
|
||||||
@ -223,6 +260,25 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
|||||||
}, nil
|
}, 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 {
|
type pushWriter struct {
|
||||||
base *dockerBase
|
base *dockerBase
|
||||||
ref string
|
ref string
|
||||||
@ -296,7 +352,7 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
|
|||||||
}
|
}
|
||||||
|
|
||||||
if size > 0 && size != status.Offset {
|
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 == "" {
|
if expected == "" {
|
||||||
@ -320,3 +376,16 @@ func (pw *pushWriter) Truncate(size int64) error {
|
|||||||
// TODO: always error on manifest
|
// TODO: always error on manifest
|
||||||
return errors.New("cannot truncate remote upload")
|
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