diff --git a/go.mod b/go.mod index cef355fca..c708e4fe6 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( ) require ( + github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect @@ -32,7 +33,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/containerd/containerd v1.7.27 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -40,7 +40,7 @@ require ( github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v27.0.3+incompatible // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/docker v28.0.0+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.1 // indirect github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -126,6 +126,7 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect diff --git a/go.sum b/go.sum index 4b6f4a869..2b812af78 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,6 @@ github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII= -github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= @@ -64,8 +62,8 @@ github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvM github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= -github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.0.0+incompatible h1:Olh0KS820sJ7nPsBKChVhk5pzqcwDR15fumfAd/p9hM= +github.com/docker/docker v28.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= diff --git a/vendor/github.com/containerd/containerd/LICENSE b/vendor/github.com/containerd/containerd/LICENSE deleted file mode 100644 index 584149b6e..000000000 --- a/vendor/github.com/containerd/containerd/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - 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 - - https://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. diff --git a/vendor/github.com/containerd/containerd/NOTICE b/vendor/github.com/containerd/containerd/NOTICE deleted file mode 100644 index 8915f0277..000000000 --- a/vendor/github.com/containerd/containerd/NOTICE +++ /dev/null @@ -1,16 +0,0 @@ -Docker -Copyright 2012-2015 Docker, Inc. - -This product includes software developed at Docker, Inc. (https://www.docker.com). - -The following is courtesy of our legal counsel: - - -Use and transfer of Docker may be subject to certain restrictions by the -United States and other governments. -It is your responsibility to ensure that your use and/or transfer does not -violate applicable laws. - -For more information, please see https://www.bis.doc.gov - -See also https://www.apache.org/dev/crypto.html and/or seek legal counsel. diff --git a/vendor/github.com/containerd/containerd/pkg/userns/userns_deprecated.go b/vendor/github.com/containerd/containerd/pkg/userns/userns_deprecated.go deleted file mode 100644 index 79d22a5d1..000000000 --- a/vendor/github.com/containerd/containerd/pkg/userns/userns_deprecated.go +++ /dev/null @@ -1,29 +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. -*/ - -// Deprecated: use github.com/moby/sys/userns -package userns - -import "github.com/moby/sys/userns" - -// RunningInUserNS detects whether we are currently running in a Linux -// user namespace and memoizes the result. It returns false on non-Linux -// platforms. -// -// Deprecated: use [userns.RunningInUserNS]. -func RunningInUserNS() bool { - return userns.RunningInUserNS() -} diff --git a/vendor/github.com/docker/docker/AUTHORS b/vendor/github.com/docker/docker/AUTHORS index 5f93eeb4e..88032defe 100644 --- a/vendor/github.com/docker/docker/AUTHORS +++ b/vendor/github.com/docker/docker/AUTHORS @@ -2,7 +2,9 @@ # This file lists all contributors to the repository. # See hack/generate-authors.sh to make modifications. +7sunarni <710720732@qq.com> Aanand Prasad +Aarni Koskela Aaron Davidson Aaron Feng Aaron Hnatiw @@ -11,6 +13,7 @@ Aaron L. Xu Aaron Lehmann Aaron Welch Aaron Yoshitake +Abdur Rehman Abel Muiño Abhijeet Kasurde Abhinandan Prativadi @@ -24,9 +27,11 @@ Adam Avilla Adam Dobrawy Adam Eijdenberg Adam Kunk +Adam Lamers Adam Miller Adam Mills Adam Pointer +Adam Simon Adam Singer Adam Thornton Adam Walz @@ -119,6 +124,7 @@ amangoel Amen Belayneh Ameya Gawde Amir Goldstein +AmirBuddy Amit Bakshi Amit Krishnan Amit Shukla @@ -168,6 +174,7 @@ Andrey Kolomentsev Andrey Petrov Andrey Stolbovsky André Martins +Andrés Maldonado Andy Chambers andy diller Andy Goldstein @@ -219,6 +226,7 @@ Artur Meyster Arun Gupta Asad Saeeduddin Asbjørn Enge +Ashly Mathew Austin Vazquez averagehuman Avi Das @@ -345,6 +353,7 @@ Chance Zibolski Chander Govindarajan Chanhun Jeong Chao Wang +Charity Kathure Charles Chan Charles Hooper Charles Law @@ -480,6 +489,7 @@ Daniel Farrell Daniel Garcia Daniel Gasienica Daniel Grunwell +Daniel Guns Daniel Helfand Daniel Hiltgen Daniel J Walsh @@ -763,6 +773,7 @@ Frank Macreery Frank Rosquin Frank Villaro-Dixon Frank Yang +François Scala Fred Lifton Frederick F. Kautz IV Frederico F. de Oliveira @@ -798,6 +809,7 @@ GennadySpb Geoff Levand Geoffrey Bachelet Geon Kim +George Adams George Kontridze George Ma George MacRorie @@ -826,6 +838,7 @@ Gopikannan Venugopalsamy Gosuke Miyashita Gou Rao Govinda Fichtner +Grace Choi Grant Millar Grant Reaber Graydon Hoare @@ -966,6 +979,7 @@ James Nugent James Sanders James Turnbull James Watkins-Harvey +Jameson Hyde Jamie Hannaford Jamshid Afshar Jan Breig @@ -1064,13 +1078,16 @@ Jim Perrin Jimmy Cuadra Jimmy Puckett Jimmy Song +jinjiadu Jinsoo Park Jintao Zhang Jiri Appl Jiri Popelka Jiuyue Ma Jiří Župka +jjimbo137 <115816493+jjimbo137@users.noreply.github.com> Joakim Roubert +Joan Grau Joao Fernandes Joao Trindade Joe Beda @@ -1155,6 +1172,7 @@ Josiah Kiehl José Tomás Albornoz Joyce Jang JP +JSchltggr Julian Taylor Julien Barbier Julien Bisconti @@ -1289,6 +1307,7 @@ Laura Brehm Laura Frank Laurent Bernaille Laurent Erignoux +Laurent Goderre Laurie Voss Leandro Motta Barros Leandro Siqueira @@ -1369,6 +1388,7 @@ Madhan Raj Mookkandy Madhav Puri Madhu Venugopal Mageee +maggie44 <64841595+maggie44@users.noreply.github.com> Mahesh Tiyyagura malnick Malte Janduda @@ -1579,6 +1599,7 @@ Muayyad Alsadi Muhammad Zohaib Aslam Mustafa Akın Muthukumar R +Myeongjoon Kim Máximo Cuadros Médi-Rémi Hashim Nace Oroz @@ -1593,6 +1614,7 @@ Natasha Jarus Nate Brennand Nate Eagleson Nate Jones +Nathan Baulch Nathan Carlson Nathan Herald Nathan Hsieh @@ -1655,6 +1677,7 @@ Nuutti Kotivuori nzwsch O.S. Tezer objectified +Octol1ttle Odin Ugedal Oguz Bilgic Oh Jinkyun @@ -1763,6 +1786,7 @@ Pierre Carrier Pierre Dal-Pra Pierre Wacrenier Pierre-Alain RIVIERE +pinglanlu Piotr Bogdan Piotr Karbowski Porjo @@ -1790,6 +1814,7 @@ Quentin Tayssier r0n22 Rachit Sharma Radostin Stoyanov +Rafael Fernández López Rafal Jeczalik Rafe Colton Raghavendra K T @@ -1856,7 +1881,7 @@ Robin Speekenbrink Robin Thoni robpc Rodolfo Carvalho -Rodrigo Campos +Rodrigo Campos Rodrigo Vaz Roel Van Nyen Roger Peppe @@ -1995,6 +2020,7 @@ Sevki Hasirci Shane Canon Shane da Silva Shaun Kaasten +Shaun Thompson shaunol Shawn Landden Shawn Siefkas @@ -2013,6 +2039,7 @@ Shijun Qin Shishir Mahajan Shoubhik Bose Shourya Sarcar +Shreenidhi Shedi Shu-Wai Chow shuai-z Shukui Yang @@ -2100,6 +2127,7 @@ Sébastien Stormacq Sören Tempel Tabakhase Tadej Janež +Tadeusz Dudkiewicz Takuto Sato tang0th Tangi Colin @@ -2107,6 +2135,7 @@ Tatsuki Sugiura Tatsushi Inagaki Taylan Isikdemir Taylor Jones +tcpdumppy <847462026@qq.com> Ted M. Young Tehmasp Chaudhri Tejaswini Duggaraju @@ -2391,6 +2420,7 @@ You-Sheng Yang (楊有勝) youcai Youcef YEKHLEF Youfu Zhang +YR Chen Yu Changchun Yu Chengxia Yu Peng diff --git a/vendor/github.com/docker/docker/api/common.go b/vendor/github.com/docker/docker/api/common.go index f831735f8..2c62cd403 100644 --- a/vendor/github.com/docker/docker/api/common.go +++ b/vendor/github.com/docker/docker/api/common.go @@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api" // Common constants for daemon and client. const ( // DefaultVersion of the current REST API. - DefaultVersion = "1.46" + DefaultVersion = "1.48" // MinSupportedAPIVersion is the minimum API version that can be supported // by the API server, specified as "major.minor". Note that the daemon diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml index 78f0ce1f2..a4881f951 100644 --- a/vendor/github.com/docker/docker/api/swagger.yaml +++ b/vendor/github.com/docker/docker/api/swagger.yaml @@ -19,10 +19,10 @@ produces: consumes: - "application/json" - "text/plain" -basePath: "/v1.46" +basePath: "/v1.48" info: title: "Docker Engine API" - version: "1.46" + version: "1.48" x-logo: url: "https://docs.docker.com/assets/images/logo-docker-main.png" description: | @@ -55,14 +55,14 @@ info: the URL is not supported by the daemon, a HTTP `400 Bad Request` error message is returned. - If you omit the version-prefix, the current version of the API (v1.46) is used. - For example, calling `/info` is the same as calling `/v1.46/info`. Using the + If you omit the version-prefix, the current version of the API (v1.48) is used. + For example, calling `/info` is the same as calling `/v1.48/info`. Using the API without a version-prefix is deprecated and will be removed in a future release. Engine releases in the near future should support this version of the API, so your client will continue to work even if it is talking to a newer Engine. - The API uses an open schema model, which means server may add extra properties + The API uses an open schema model, which means the server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer @@ -212,6 +212,7 @@ definitions: - `bind` a mount of a file or directory from the host into the container. - `volume` a docker volume with the given `Name`. + - `image` a docker image - `tmpfs` a `tmpfs`. - `npipe` a named pipe from the host into the container. - `cluster` a Swarm cluster volume @@ -219,6 +220,7 @@ definitions: enum: - "bind" - "volume" + - "image" - "tmpfs" - "npipe" - "cluster" @@ -350,6 +352,7 @@ definitions: - `bind` Mounts a file or directory from the host into the container. Must exist prior to creating the container. - `volume` Creates a volume with the given name and options (or uses a pre-existing volume with the same name and options). These are **not** removed when the container is removed. + - `image` Mounts an image. - `tmpfs` Create a tmpfs with the given options. The mount source cannot be specified for tmpfs. - `npipe` Mounts a named pipe from the host into the container. Must exist prior to creating the container. - `cluster` a Swarm cluster volume @@ -357,6 +360,7 @@ definitions: enum: - "bind" - "volume" + - "image" - "tmpfs" - "npipe" - "cluster" @@ -393,7 +397,7 @@ definitions: Make the mount non-recursively read-only, but still leave the mount recursive (unless NonRecursive is set to `true` in conjunction). - Addded in v1.44, before that version all read-only mounts were + Added in v1.44, before that version all read-only mounts were non-recursive by default. To match the previous behaviour this will default to `true` for clients on versions prior to v1.44. type: "boolean" @@ -431,6 +435,14 @@ definitions: description: "Source path inside the volume. Must be relative without any back traversals." type: "string" example: "dir-inside-volume/subdirectory" + ImageOptions: + description: "Optional configuration for the `image` type." + type: "object" + properties: + Subpath: + description: "Source path inside the image. Must be relative without any back traversals." + type: "string" + example: "dir-inside-image/subdirectory" TmpfsOptions: description: "Optional configuration for the `tmpfs` type." type: "object" @@ -953,13 +965,18 @@ definitions: ContainerIDFile: type: "string" description: "Path to a file where the container ID is written" + example: "" LogConfig: type: "object" description: "The logging configuration for this container" properties: Type: + description: |- + Name of the logging driver used for the container or "none" + if logging is disabled. type: "string" enum: + - "local" - "json-file" - "syslog" - "journald" @@ -970,9 +987,14 @@ definitions: - "etwlogs" - "none" Config: + description: |- + Driver-specific configuration options for the logging driver. type: "object" additionalProperties: type: "string" + example: + "max-file": "5" + "max-size": "10m" NetworkMode: type: "string" description: | @@ -1015,6 +1037,7 @@ definitions: items: type: "integer" minimum: 0 + example: [80, 64] Annotations: type: "object" description: | @@ -1117,7 +1140,8 @@ definitions: - `"host"`: use the host's PID namespace inside the container Privileged: type: "boolean" - description: "Gives the container full access to the host." + description: |- + Gives the container full access to the host. PublishAllPorts: type: "boolean" description: | @@ -1174,18 +1198,20 @@ definitions: minimum: 0 Sysctls: type: "object" - description: | + x-nullable: true + description: |- A list of kernel parameters (sysctls) to set in the container. - For example: - ``` - {"net.ipv4.ip_forward": "1"} - ``` + This field is omitted if not set. additionalProperties: type: "string" + example: + "net.ipv4.ip_forward": "1" Runtime: type: "string" - description: "Runtime to use with this container." + x-nullable: true + description: |- + Runtime to use with this container. # Applicable to Windows Isolation: type: "string" @@ -1195,6 +1221,7 @@ definitions: - "default" - "process" - "hyperv" + - "" MaskedPaths: type: "array" description: | @@ -1202,6 +1229,18 @@ definitions: the default set of paths). items: type: "string" + example: + - "/proc/asound" + - "/proc/acpi" + - "/proc/kcore" + - "/proc/keys" + - "/proc/latency_stats" + - "/proc/timer_list" + - "/proc/timer_stats" + - "/proc/sched_debug" + - "/proc/scsi" + - "/sys/firmware" + - "/sys/devices/virtual/powercap" ReadonlyPaths: type: "array" description: | @@ -1209,6 +1248,12 @@ definitions: (this overrides the default set of paths). items: type: "string" + example: + - "/proc/bus" + - "/proc/fs" + - "/proc/irq" + - "/proc/sys" + - "/proc/sysrq-trigger" ContainerConfig: description: | @@ -1225,8 +1270,14 @@ definitions: The domain name to use for the container. type: "string" User: - description: "The user that commands are run as inside the container." + description: |- + Commands run as this user inside the container. If omitted, commands + run as the user specified in the image the container was started from. + + Can be either user-name or UID, and optional group-name or GID, + separated by a colon (`[<:group-name|GID>]`). type: "string" + example: "123:456" AttachStdin: description: "Whether to attach to `stdin`." type: "boolean" @@ -1384,7 +1435,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always empty. It must not be used, and will be removed in API v1.47. + > always empty. It must not be used, and will be removed in API v1.48. type: "string" example: "" Domainname: @@ -1394,7 +1445,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always empty. It must not be used, and will be removed in API v1.47. + > always empty. It must not be used, and will be removed in API v1.48. type: "string" example: "" User: @@ -1408,7 +1459,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1419,7 +1470,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1430,7 +1481,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1457,7 +1508,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1468,7 +1519,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1479,7 +1530,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1516,7 +1567,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always empty. It must not be used, and will be removed in API v1.47. + > always empty. It must not be used, and will be removed in API v1.48. type: "string" default: "" example: "" @@ -1555,7 +1606,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always omitted. It must not be used, and will be removed in API v1.47. + > always omitted. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1567,7 +1618,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always omitted. It must not be used, and will be removed in API v1.47. + > always omitted. It must not be used, and will be removed in API v1.48. type: "string" default: "" example: "" @@ -1601,7 +1652,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always omitted. It must not be used, and will be removed in API v1.47. + > always omitted. It must not be used, and will be removed in API v1.48. type: "integer" default: 10 x-nullable: true @@ -1917,7 +1968,7 @@ definitions: type: "string" example: "4443" - GraphDriverData: + DriverData: description: | Information about the storage driver used to store the container's and image's filesystem. @@ -1991,6 +2042,33 @@ definitions: type: "string" x-nullable: false example: "sha256:ec3f0931a6e6b6855d76b2d7b0be30e81860baccd891b2e243280bf1cd8ad710" + Descriptor: + description: | + Descriptor is an OCI descriptor of the image target. + In case of a multi-platform image, this descriptor points to the OCI index + or a manifest list. + + This field is only present if the daemon provides a multi-platform image store. + + WARNING: This is experimental and may change at any time without any backward + compatibility. + x-nullable: true + $ref: "#/definitions/OCIDescriptor" + Manifests: + description: | + Manifests is a list of image manifests available in this image. It + provides a more detailed view of the platform-specific image manifests or + other image-attached data like build attestations. + + Only available if the daemon provides a multi-platform image store + and the `manifests` option is set in the inspect request. + + WARNING: This is experimental and may change at any time without any backward + compatibility. + type: "array" + x-nullable: true + items: + $ref: "#/definitions/ImageManifestSummary" RepoTags: description: | List of image names/tags in the local image cache that reference this @@ -2107,7 +2185,7 @@ definitions: format: "int64" example: 1239828 GraphDriver: - $ref: "#/definitions/GraphDriverData" + $ref: "#/definitions/DriverData" RootFS: description: | Information about the image's RootFS, including the layer IDs. @@ -2216,7 +2294,7 @@ definitions: Created: description: | Date and time at which the image was created as a Unix timestamp - (number of seconds sinds EPOCH). + (number of seconds since EPOCH). type: "integer" x-nullable: false example: "1644009612" @@ -2265,6 +2343,31 @@ definitions: x-nullable: false type: "integer" example: 2 + Manifests: + description: | + Manifests is a list of manifests available in this image. + It provides a more detailed view of the platform-specific image manifests + or other image-attached data like build attestations. + + WARNING: This is experimental and may change at any time without any backward + compatibility. + type: "array" + x-nullable: false + x-omitempty: true + items: + $ref: "#/definitions/ImageManifestSummary" + Descriptor: + description: | + Descriptor is an OCI descriptor of the image target. + In case of a multi-platform image, this descriptor points to the OCI index + or a manifest list. + + This field is only present if the daemon provides a multi-platform image store. + + WARNING: This is experimental and may change at any time without any backward + compatibility. + x-nullable: true + $ref: "#/definitions/OCIDescriptor" AuthConfig: type: "object" @@ -2484,6 +2587,11 @@ definitions: `overlay`). type: "string" example: "overlay" + EnableIPv4: + description: | + Whether the network was created with IPv4 enabled. + type: "boolean" + example: true EnableIPv6: description: | Whether the network was created with IPv6 enabled. @@ -2500,7 +2608,7 @@ definitions: example: false Attachable: description: | - Wheter a global / swarm scope network is manually attachable by regular + Whether a global / swarm scope network is manually attachable by regular containers from workers in swarm mode. type: "boolean" default: false @@ -2684,12 +2792,24 @@ definitions: type: "string" error: type: "string" + x-nullable: true + description: |- + errors encountered during the operation. + + + > **Deprecated**: This field is deprecated since API v1.4, and will be omitted in a future API version. Use the information in errorDetail instead. errorDetail: $ref: "#/definitions/ErrorDetail" status: type: "string" progress: type: "string" + x-nullable: true + description: |- + Progress is a pre-formatted presentation of progressDetail. + + + > **Deprecated**: This field is deprecated since API v1.8, and will be omitted in a future API version. Use the information in progressDetail instead. progressDetail: $ref: "#/definitions/ProgressDetail" aux: @@ -2789,12 +2909,24 @@ definitions: type: "string" error: type: "string" + x-nullable: true + description: |- + errors encountered during the operation. + + + > **Deprecated**: This field is deprecated since API v1.4, and will be omitted in a future API version. Use the information in errorDetail instead. errorDetail: $ref: "#/definitions/ErrorDetail" status: type: "string" progress: type: "string" + x-nullable: true + description: |- + Progress is a pre-formatted presentation of progressDetail. + + + > **Deprecated**: This field is deprecated since API v1.8, and will be omitted in a future API version. Use the information in progressDetail instead. progressDetail: $ref: "#/definitions/ProgressDetail" @@ -2803,10 +2935,24 @@ definitions: properties: error: type: "string" + x-nullable: true + description: |- + errors encountered during the operation. + + + > **Deprecated**: This field is deprecated since API v1.4, and will be omitted in a future API version. Use the information in errorDetail instead. + errorDetail: + $ref: "#/definitions/ErrorDetail" status: type: "string" progress: type: "string" + x-nullable: true + description: |- + Progress is a pre-formatted presentation of progressDetail. + + + > **Deprecated**: This field is deprecated since API v1.8, and will be omitted in a future API version. Use the information in progressDetail instead. progressDetail: $ref: "#/definitions/ProgressDetail" @@ -2838,9 +2984,10 @@ definitions: example: message: "Something went wrong." - IdResponse: + IDResponse: description: "Response to an API call that returns just an Id" type: "object" + x-go-name: "IDResponse" required: ["Id"] properties: Id: @@ -2885,6 +3032,16 @@ definitions: example: com.example.some-label: "some-value" com.example.some-other-label: "some-other-value" + GwPriority: + description: | + This property determines which endpoint will provide the default + gateway for a container. The endpoint with the highest priority will + be used. If multiple endpoints have the same priority, endpoints are + lexicographically sorted based on their network name, and the one + that sorts first is picked. + type: "number" + example: + - 10 # Operational data NetworkID: @@ -3723,7 +3880,7 @@ definitions: example: "json-file" Options: description: | - Driver-specific options for the selectd log driver, specified + Driver-specific options for the selected log driver, specified as key/value pairs. type: "object" additionalProperties: @@ -4167,6 +4324,7 @@ definitions: - "default" - "process" - "hyperv" + - "" Init: description: | Run an init inside the container that forwards signals and reaps @@ -4971,76 +5129,346 @@ definitions: Warnings: - "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found" + ContainerInspectResponse: + type: "object" + title: "ContainerInspectResponse" + x-go-name: "InspectResponse" + properties: + Id: + description: |- + The ID of this container as a 128-bit (64-character) hexadecimal string (32 bytes). + type: "string" + x-go-name: "ID" + minLength: 64 + maxLength: 64 + pattern: "^[0-9a-fA-F]{64}$" + example: "aa86eacfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf" + Created: + description: |- + Date and time at which the container was created, formatted in + [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. + type: "string" + format: "dateTime" + x-nullable: true + example: "2025-02-17T17:43:39.64001363Z" + Path: + description: |- + The path to the command being run + type: "string" + example: "/bin/sh" + Args: + description: "The arguments to the command being run" + type: "array" + items: + type: "string" + example: + - "-c" + - "exit 9" + State: + $ref: "#/definitions/ContainerState" + Image: + description: |- + The ID (digest) of the image that this container was created from. + type: "string" + example: "sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782" + ResolvConfPath: + description: |- + Location of the `/etc/resolv.conf` generated for the container on the + host. + + This file is managed through the docker daemon, and should not be + accessed or modified by other tools. + type: "string" + example: "/var/lib/docker/containers/aa86eacfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf/resolv.conf" + HostnamePath: + description: |- + Location of the `/etc/hostname` generated for the container on the + host. + + This file is managed through the docker daemon, and should not be + accessed or modified by other tools. + type: "string" + example: "/var/lib/docker/containers/aa86eacfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf/hostname" + HostsPath: + description: |- + Location of the `/etc/hosts` generated for the container on the + host. + + This file is managed through the docker daemon, and should not be + accessed or modified by other tools. + type: "string" + example: "/var/lib/docker/containers/aa86eacfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf/hosts" + LogPath: + description: |- + Location of the file used to buffer the container's logs. Depending on + the logging-driver used for the container, this field may be omitted. + + This file is managed through the docker daemon, and should not be + accessed or modified by other tools. + type: "string" + x-nullable: true + example: "/var/lib/docker/containers/5b7c7e2b992aa426584ce6c47452756066be0e503a08b4516a433a54d2f69e59/5b7c7e2b992aa426584ce6c47452756066be0e503a08b4516a433a54d2f69e59-json.log" + Name: + description: |- + The name associated with this container. + + For historic reasons, the name may be prefixed with a forward-slash (`/`). + type: "string" + example: "/funny_chatelet" + RestartCount: + description: |- + Number of times the container was restarted since it was created, + or since daemon was started. + type: "integer" + example: 0 + Driver: + description: |- + The storage-driver used for the container's filesystem (graph-driver + or snapshotter). + type: "string" + example: "overlayfs" + Platform: + description: |- + The platform (operating system) for which the container was created. + + This field was introduced for the experimental "LCOW" (Linux Containers + On Windows) features, which has been removed. In most cases, this field + is equal to the host's operating system (`linux` or `windows`). + type: "string" + example: "linux" + ImageManifestDescriptor: + $ref: "#/definitions/OCIDescriptor" + description: |- + OCI descriptor of the platform-specific manifest of the image + the container was created from. + + Note: Only available if the daemon provides a multi-platform + image store. + MountLabel: + description: |- + SELinux mount label set for the container. + type: "string" + example: "" + ProcessLabel: + description: |- + SELinux process label set for the container. + type: "string" + example: "" + AppArmorProfile: + description: |- + The AppArmor profile set for the container. + type: "string" + example: "" + ExecIDs: + description: |- + IDs of exec instances that are running in the container. + type: "array" + items: + type: "string" + x-nullable: true + example: + - "b35395de42bc8abd327f9dd65d913b9ba28c74d2f0734eeeae84fa1c616a0fca" + - "3fc1232e5cd20c8de182ed81178503dc6437f4e7ef12b52cc5e8de020652f1c4" + HostConfig: + $ref: "#/definitions/HostConfig" + GraphDriver: + $ref: "#/definitions/DriverData" + SizeRw: + description: |- + The size of files that have been created or changed by this container. + + This field is omitted by default, and only set when size is requested + in the API request. + type: "integer" + format: "int64" + x-nullable: true + example: "122880" + SizeRootFs: + description: |- + The total size of all files in the read-only layers from the image + that the container uses. These layers can be shared between containers. + + This field is omitted by default, and only set when size is requested + in the API request. + type: "integer" + format: "int64" + x-nullable: true + example: "1653948416" + Mounts: + description: |- + List of mounts used by the container. + type: "array" + items: + $ref: "#/definitions/MountPoint" + Config: + $ref: "#/definitions/ContainerConfig" + NetworkSettings: + $ref: "#/definitions/NetworkSettings" + ContainerSummary: type: "object" properties: Id: - description: "The ID of this container" + description: |- + The ID of this container as a 128-bit (64-character) hexadecimal string (32 bytes). type: "string" x-go-name: "ID" + minLength: 64 + maxLength: 64 + pattern: "^[0-9a-fA-F]{64}$" + example: "aa86eacfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf" Names: - description: "The names that this container has been given" + description: |- + The names associated with this container. Most containers have a single + name, but when using legacy "links", the container can have multiple + names. + + For historic reasons, names are prefixed with a forward-slash (`/`). type: "array" items: type: "string" + example: + - "/funny_chatelet" Image: - description: "The name of the image used when creating this container" + description: |- + The name or ID of the image used to create the container. + + This field shows the image reference as was specified when creating the container, + which can be in its canonical form (e.g., `docker.io/library/ubuntu:latest` + or `docker.io/library/ubuntu@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782`), + short form (e.g., `ubuntu:latest`)), or the ID(-prefix) of the image (e.g., `72297848456d`). + + The content of this field can be updated at runtime if the image used to + create the container is untagged, in which case the field is updated to + contain the the image ID (digest) it was resolved to in its canonical, + non-truncated form (e.g., `sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782`). type: "string" + example: "docker.io/library/ubuntu:latest" ImageID: - description: "The ID of the image that this container was created from" + description: |- + The ID (digest) of the image that this container was created from. type: "string" + example: "sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782" + ImageManifestDescriptor: + $ref: "#/definitions/OCIDescriptor" + x-nullable: true + description: | + OCI descriptor of the platform-specific manifest of the image + the container was created from. + + Note: Only available if the daemon provides a multi-platform + image store. + + This field is not populated in the `GET /system/df` endpoint. Command: description: "Command to run when starting the container" type: "string" + example: "/bin/bash" Created: - description: "When the container was created" + description: |- + Date and time at which the container was created as a Unix timestamp + (number of seconds since EPOCH). type: "integer" format: "int64" + example: "1739811096" Ports: - description: "The ports exposed by this container" + description: |- + Port-mappings for the container. type: "array" items: $ref: "#/definitions/Port" SizeRw: - description: "The size of files that have been created or changed by this container" + description: |- + The size of files that have been created or changed by this container. + + This field is omitted by default, and only set when size is requested + in the API request. type: "integer" format: "int64" + x-nullable: true + example: "122880" SizeRootFs: - description: "The total size of all the files in this container" + description: |- + The total size of all files in the read-only layers from the image + that the container uses. These layers can be shared between containers. + + This field is omitted by default, and only set when size is requested + in the API request. type: "integer" format: "int64" + x-nullable: true + example: "1653948416" Labels: description: "User-defined key/value metadata." type: "object" additionalProperties: type: "string" + example: + com.example.vendor: "Acme" + com.example.license: "GPL" + com.example.version: "1.0" State: - description: "The state of this container (e.g. `Exited`)" + description: | + The state of this container. type: "string" + enum: + - "created" + - "running" + - "paused" + - "restarting" + - "exited" + - "removing" + - "dead" + example: "running" Status: - description: "Additional human-readable status of this container (e.g. `Exit 0`)" + description: |- + Additional human-readable status of this container (e.g. `Exit 0`) type: "string" + example: "Up 4 days" HostConfig: type: "object" + description: |- + Summary of host-specific runtime information of the container. This + is a reduced set of information in the container's "HostConfig" as + available in the container "inspect" response. properties: NetworkMode: + description: |- + Networking mode (`host`, `none`, `container:`) or name of the + primary network the container is using. + + This field is primarily for backward compatibility. The container + can be connected to multiple networks for which information can be + found in the `NetworkSettings.Networks` field, which enumerates + settings per network. type: "string" + example: "mynetwork" Annotations: - description: "Arbitrary key-value metadata attached to container" + description: |- + Arbitrary key-value metadata attached to the container. type: "object" x-nullable: true additionalProperties: type: "string" + example: + io.kubernetes.docker.type: "container" + io.kubernetes.sandbox.id: "3befe639bed0fd6afdd65fd1fa84506756f59360ec4adc270b0fdac9be22b4d3" NetworkSettings: - description: "A summary of the container's network settings" + description: |- + Summary of the container's network settings type: "object" properties: Networks: type: "object" + description: |- + Summary of network-settings for each network the container is + attached to. additionalProperties: $ref: "#/definitions/EndpointSettings" Mounts: type: "array" + description: |- + List of mounts used by the container. items: $ref: "#/definitions/MountPoint" @@ -5245,52 +5673,664 @@ definitions: type: "string" example: [] - ContainerWaitResponse: - description: "OK response to ContainerWait operation" + ContainerUpdateResponse: type: "object" - x-go-name: "WaitResponse" - title: "ContainerWaitResponse" - required: [StatusCode] + title: "ContainerUpdateResponse" + x-go-name: "UpdateResponse" + description: |- + Response for a successful container-update. properties: - StatusCode: - description: "Exit code of the container" - type: "integer" - format: "int64" - x-nullable: false - Error: - $ref: "#/definitions/ContainerWaitExitError" + Warnings: + type: "array" + description: |- + Warnings encountered when updating the container. + items: + type: "string" + example: ["Published ports are discarded when using host network mode"] - ContainerWaitExitError: - description: "container waiting error, if any" + ContainerStatsResponse: + description: | + Statistics sample for a container. type: "object" - x-go-name: "WaitExitError" + x-go-name: "StatsResponse" + title: "ContainerStatsResponse" properties: - Message: - description: "Details of an error" + name: + description: "Name of the container" + type: "string" + x-nullable: true + example: "boring_wozniak" + id: + description: "ID of the container" type: "string" + x-nullable: true + example: "ede54ee1afda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c743" + read: + description: | + Date and time at which this sample was collected. + The value is formatted as [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) + with nano-seconds. + type: "string" + format: "date-time" + example: "2025-01-16T13:55:22.165243637Z" + preread: + description: | + Date and time at which this first sample was collected. This field + is not propagated if the "one-shot" option is set. If the "one-shot" + option is set, this field may be omitted, empty, or set to a default + date (`0001-01-01T00:00:00Z`). - SystemVersion: - type: "object" + The value is formatted as [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) + with nano-seconds. + type: "string" + format: "date-time" + example: "2025-01-16T13:55:21.160452595Z" + pids_stats: + $ref: "#/definitions/ContainerPidsStats" + blkio_stats: + $ref: "#/definitions/ContainerBlkioStats" + num_procs: + description: | + The number of processors on the system. + + This field is Windows-specific and always zero for Linux containers. + type: "integer" + format: "uint32" + example: 16 + storage_stats: + $ref: "#/definitions/ContainerStorageStats" + cpu_stats: + $ref: "#/definitions/ContainerCPUStats" + precpu_stats: + $ref: "#/definitions/ContainerCPUStats" + memory_stats: + $ref: "#/definitions/ContainerMemoryStats" + networks: + description: | + Network statistics for the container per interface. + + This field is omitted if the container has no networking enabled. + x-nullable: true + additionalProperties: + $ref: "#/definitions/ContainerNetworkStats" + example: + eth0: + rx_bytes: 5338 + rx_dropped: 0 + rx_errors: 0 + rx_packets: 36 + tx_bytes: 648 + tx_dropped: 0 + tx_errors: 0 + tx_packets: 8 + eth5: + rx_bytes: 4641 + rx_dropped: 0 + rx_errors: 0 + rx_packets: 26 + tx_bytes: 690 + tx_dropped: 0 + tx_errors: 0 + tx_packets: 9 + + ContainerBlkioStats: description: | - Response of Engine API: GET "/version" + BlkioStats stores all IO service stats for data read and write. + + This type is Linux-specific and holds many fields that are specific to cgroups v1. + On a cgroup v2 host, all fields other than `io_service_bytes_recursive` + are omitted or `null`. + + This type is only populated on Linux and omitted for Windows containers. + type: "object" + x-go-name: "BlkioStats" + x-nullable: true properties: - Platform: - type: "object" - required: [Name] - properties: - Name: - type: "string" - Components: + io_service_bytes_recursive: type: "array" + items: + $ref: "#/definitions/ContainerBlkioStatEntry" + io_serviced_recursive: description: | - Information about system components + This field is only available when using Linux containers with + cgroups v1. It is omitted or `null` when using cgroups v2. + x-nullable: true + type: "array" items: - type: "object" - x-go-name: ComponentVersion - required: [Name, Version] - properties: - Name: - description: | + $ref: "#/definitions/ContainerBlkioStatEntry" + io_queue_recursive: + description: | + This field is only available when using Linux containers with + cgroups v1. It is omitted or `null` when using cgroups v2. + x-nullable: true + type: "array" + items: + $ref: "#/definitions/ContainerBlkioStatEntry" + io_service_time_recursive: + description: | + This field is only available when using Linux containers with + cgroups v1. It is omitted or `null` when using cgroups v2. + x-nullable: true + type: "array" + items: + $ref: "#/definitions/ContainerBlkioStatEntry" + io_wait_time_recursive: + description: | + This field is only available when using Linux containers with + cgroups v1. It is omitted or `null` when using cgroups v2. + x-nullable: true + type: "array" + items: + $ref: "#/definitions/ContainerBlkioStatEntry" + io_merged_recursive: + description: | + This field is only available when using Linux containers with + cgroups v1. It is omitted or `null` when using cgroups v2. + x-nullable: true + type: "array" + items: + $ref: "#/definitions/ContainerBlkioStatEntry" + io_time_recursive: + description: | + This field is only available when using Linux containers with + cgroups v1. It is omitted or `null` when using cgroups v2. + x-nullable: true + type: "array" + items: + $ref: "#/definitions/ContainerBlkioStatEntry" + sectors_recursive: + description: | + This field is only available when using Linux containers with + cgroups v1. It is omitted or `null` when using cgroups v2. + x-nullable: true + type: "array" + items: + $ref: "#/definitions/ContainerBlkioStatEntry" + example: + io_service_bytes_recursive: [ + {"major": 254, "minor": 0, "op": "read", "value": 7593984}, + {"major": 254, "minor": 0, "op": "write", "value": 100} + ] + io_serviced_recursive: null + io_queue_recursive: null + io_service_time_recursive: null + io_wait_time_recursive: null + io_merged_recursive: null + io_time_recursive: null + sectors_recursive: null + + ContainerBlkioStatEntry: + description: | + Blkio stats entry. + + This type is Linux-specific and omitted for Windows containers. + type: "object" + x-go-name: "BlkioStatEntry" + x-nullable: true + properties: + major: + type: "integer" + format: "uint64" + example: 254 + minor: + type: "integer" + format: "uint64" + example: 0 + op: + type: "string" + example: "read" + value: + type: "integer" + format: "uint64" + example: 7593984 + + ContainerCPUStats: + description: | + CPU related info of the container + type: "object" + x-go-name: "CPUStats" + x-nullable: true + properties: + cpu_usage: + $ref: "#/definitions/ContainerCPUUsage" + system_cpu_usage: + description: | + System Usage. + + This field is Linux-specific and omitted for Windows containers. + type: "integer" + format: "uint64" + x-nullable: true + example: 5 + online_cpus: + description: | + Number of online CPUs. + + This field is Linux-specific and omitted for Windows containers. + type: "integer" + format: "uint32" + x-nullable: true + example: 5 + throttling_data: + $ref: "#/definitions/ContainerThrottlingData" + + ContainerCPUUsage: + description: | + All CPU stats aggregated since container inception. + type: "object" + x-go-name: "CPUUsage" + x-nullable: true + properties: + total_usage: + description: | + Total CPU time consumed in nanoseconds (Linux) or 100's of nanoseconds (Windows). + type: "integer" + format: "uint64" + example: 29912000 + percpu_usage: + description: | + Total CPU time (in nanoseconds) consumed per core (Linux). + + This field is Linux-specific when using cgroups v1. It is omitted + when using cgroups v2 and Windows containers. + type: "array" + x-nullable: true + items: + type: "integer" + format: "uint64" + example: 29912000 + + usage_in_kernelmode: + description: | + Time (in nanoseconds) spent by tasks of the cgroup in kernel mode (Linux), + or time spent (in 100's of nanoseconds) by all container processes in + kernel mode (Windows). + + Not populated for Windows containers using Hyper-V isolation. + type: "integer" + format: "uint64" + example: 21994000 + usage_in_usermode: + description: | + Time (in nanoseconds) spent by tasks of the cgroup in user mode (Linux), + or time spent (in 100's of nanoseconds) by all container processes in + kernel mode (Windows). + + Not populated for Windows containers using Hyper-V isolation. + type: "integer" + format: "uint64" + example: 7918000 + + ContainerPidsStats: + description: | + PidsStats contains Linux-specific stats of a container's process-IDs (PIDs). + + This type is Linux-specific and omitted for Windows containers. + type: "object" + x-go-name: "PidsStats" + x-nullable: true + properties: + current: + description: | + Current is the number of PIDs in the cgroup. + type: "integer" + format: "uint64" + x-nullable: true + example: 5 + limit: + description: | + Limit is the hard limit on the number of pids in the cgroup. + A "Limit" of 0 means that there is no limit. + type: "integer" + format: "uint64" + x-nullable: true + example: 18446744073709551615 + + ContainerThrottlingData: + description: | + CPU throttling stats of the container. + + This type is Linux-specific and omitted for Windows containers. + type: "object" + x-go-name: "ThrottlingData" + x-nullable: true + properties: + periods: + description: | + Number of periods with throttling active. + type: "integer" + format: "uint64" + example: 0 + throttled_periods: + description: | + Number of periods when the container hit its throttling limit. + type: "integer" + format: "uint64" + example: 0 + throttled_time: + description: | + Aggregated time (in nanoseconds) the container was throttled for. + type: "integer" + format: "uint64" + example: 0 + + ContainerMemoryStats: + description: | + Aggregates all memory stats since container inception on Linux. + Windows returns stats for commit and private working set only. + type: "object" + x-go-name: "MemoryStats" + properties: + usage: + description: | + Current `res_counter` usage for memory. + + This field is Linux-specific and omitted for Windows containers. + type: "integer" + format: "uint64" + x-nullable: true + example: 0 + max_usage: + description: | + Maximum usage ever recorded. + + This field is Linux-specific and only supported on cgroups v1. + It is omitted when using cgroups v2 and for Windows containers. + type: "integer" + format: "uint64" + x-nullable: true + example: 0 + stats: + description: | + All the stats exported via memory.stat. when using cgroups v2. + + This field is Linux-specific and omitted for Windows containers. + type: "object" + additionalProperties: + type: "integer" + format: "uint64" + x-nullable: true + example: + { + "active_anon": 1572864, + "active_file": 5115904, + "anon": 1572864, + "anon_thp": 0, + "file": 7626752, + "file_dirty": 0, + "file_mapped": 2723840, + "file_writeback": 0, + "inactive_anon": 0, + "inactive_file": 2510848, + "kernel_stack": 16384, + "pgactivate": 0, + "pgdeactivate": 0, + "pgfault": 2042, + "pglazyfree": 0, + "pglazyfreed": 0, + "pgmajfault": 45, + "pgrefill": 0, + "pgscan": 0, + "pgsteal": 0, + "shmem": 0, + "slab": 1180928, + "slab_reclaimable": 725576, + "slab_unreclaimable": 455352, + "sock": 0, + "thp_collapse_alloc": 0, + "thp_fault_alloc": 1, + "unevictable": 0, + "workingset_activate": 0, + "workingset_nodereclaim": 0, + "workingset_refault": 0 + } + failcnt: + description: | + Number of times memory usage hits limits. + + This field is Linux-specific and only supported on cgroups v1. + It is omitted when using cgroups v2 and for Windows containers. + type: "integer" + format: "uint64" + x-nullable: true + example: 0 + limit: + description: | + This field is Linux-specific and omitted for Windows containers. + type: "integer" + format: "uint64" + x-nullable: true + example: 8217579520 + commitbytes: + description: | + Committed bytes. + + This field is Windows-specific and omitted for Linux containers. + type: "integer" + format: "uint64" + x-nullable: true + example: 0 + commitpeakbytes: + description: | + Peak committed bytes. + + This field is Windows-specific and omitted for Linux containers. + type: "integer" + format: "uint64" + x-nullable: true + example: 0 + privateworkingset: + description: | + Private working set. + + This field is Windows-specific and omitted for Linux containers. + type: "integer" + format: "uint64" + x-nullable: true + example: 0 + + ContainerNetworkStats: + description: | + Aggregates the network stats of one container + type: "object" + x-go-name: "NetworkStats" + x-nullable: true + properties: + rx_bytes: + description: | + Bytes received. Windows and Linux. + type: "integer" + format: "uint64" + example: 5338 + rx_packets: + description: | + Packets received. Windows and Linux. + type: "integer" + format: "uint64" + example: 36 + rx_errors: + description: | + Received errors. Not used on Windows. + + This field is Linux-specific and always zero for Windows containers. + type: "integer" + format: "uint64" + example: 0 + rx_dropped: + description: | + Incoming packets dropped. Windows and Linux. + type: "integer" + format: "uint64" + example: 0 + tx_bytes: + description: | + Bytes sent. Windows and Linux. + type: "integer" + format: "uint64" + example: 1200 + tx_packets: + description: | + Packets sent. Windows and Linux. + type: "integer" + format: "uint64" + example: 12 + tx_errors: + description: | + Sent errors. Not used on Windows. + + This field is Linux-specific and always zero for Windows containers. + type: "integer" + format: "uint64" + example: 0 + tx_dropped: + description: | + Outgoing packets dropped. Windows and Linux. + type: "integer" + format: "uint64" + example: 0 + endpoint_id: + description: | + Endpoint ID. Not used on Linux. + + This field is Windows-specific and omitted for Linux containers. + type: "string" + x-nullable: true + instance_id: + description: | + Instance ID. Not used on Linux. + + This field is Windows-specific and omitted for Linux containers. + type: "string" + x-nullable: true + + ContainerStorageStats: + description: | + StorageStats is the disk I/O stats for read/write on Windows. + + This type is Windows-specific and omitted for Linux containers. + type: "object" + x-go-name: "StorageStats" + x-nullable: true + properties: + read_count_normalized: + type: "integer" + format: "uint64" + x-nullable: true + example: 7593984 + read_size_bytes: + type: "integer" + format: "uint64" + x-nullable: true + example: 7593984 + write_count_normalized: + type: "integer" + format: "uint64" + x-nullable: true + example: 7593984 + write_size_bytes: + type: "integer" + format: "uint64" + x-nullable: true + example: 7593984 + + ContainerTopResponse: + type: "object" + x-go-name: "TopResponse" + title: "ContainerTopResponse" + description: |- + Container "top" response. + properties: + Titles: + description: "The ps column titles" + type: "array" + items: + type: "string" + example: + Titles: + - "UID" + - "PID" + - "PPID" + - "C" + - "STIME" + - "TTY" + - "TIME" + - "CMD" + Processes: + description: |- + Each process running in the container, where each process + is an array of values corresponding to the titles. + type: "array" + items: + type: "array" + items: + type: "string" + example: + Processes: + - + - "root" + - "13642" + - "882" + - "0" + - "17:03" + - "pts/0" + - "00:00:00" + - "/bin/bash" + - + - "root" + - "13735" + - "13642" + - "0" + - "17:06" + - "pts/0" + - "00:00:00" + - "sleep 10" + + ContainerWaitResponse: + description: "OK response to ContainerWait operation" + type: "object" + x-go-name: "WaitResponse" + title: "ContainerWaitResponse" + required: [StatusCode] + properties: + StatusCode: + description: "Exit code of the container" + type: "integer" + format: "int64" + x-nullable: false + Error: + $ref: "#/definitions/ContainerWaitExitError" + + ContainerWaitExitError: + description: "container waiting error, if any" + type: "object" + x-go-name: "WaitExitError" + properties: + Message: + description: "Details of an error" + type: "string" + + SystemVersion: + type: "object" + description: | + Response of Engine API: GET "/version" + properties: + Platform: + type: "object" + required: [Name] + properties: + Name: + type: "string" + Components: + type: "array" + description: | + Information about system components + items: + type: "object" + x-go-name: ComponentVersion + required: [Name, Version] + properties: + Name: + description: | Name of the component type: "string" example: "Engine" @@ -5318,7 +6358,7 @@ definitions: description: | The default (and highest) API version that is supported by the daemon type: "string" - example: "1.46" + example: "1.47" MinAPIVersion: description: | The minimum API version that is supported by the daemon @@ -5334,7 +6374,7 @@ definitions: The version Go used to compile the daemon, and the version of the Go runtime in use. type: "string" - example: "go1.21.12" + example: "go1.22.7" Os: description: | The operating system that the daemon is running on ("linux" or "windows") @@ -5494,13 +6534,28 @@ definitions: type: "boolean" example: true BridgeNfIptables: - description: "Indicates if `bridge-nf-call-iptables` is available on the host." + description: | + Indicates if `bridge-nf-call-iptables` is available on the host when + the daemon was started. + +


+ + > **Deprecated**: netfilter module is now loaded on-demand and no longer + > during daemon startup, making this field obsolete. This field is always + > `false` and will be removed in a API v1.49. type: "boolean" - example: true + example: false BridgeNfIp6tables: - description: "Indicates if `bridge-nf-call-ip6tables` is available on the host." + description: | + Indicates if `bridge-nf-call-ip6tables` is available on the host. + +


+ + > **Deprecated**: netfilter module is now loaded on-demand, and no longer + > during daemon startup, making this field obsolete. This field is always + > `false` and will be removed in a API v1.49. type: "boolean" - example: true + example: false Debug: description: | Indicates if the daemon is running in debug-mode / with debug-level @@ -5737,6 +6792,7 @@ definitions: - "default" - "hyperv" - "process" + - "" InitBinary: description: | Name and, optional, path of the `docker-init` binary. @@ -5807,8 +6863,6 @@ definitions: type: "string" example: - "WARNING: No memory limit support" - - "WARNING: bridge-nf-call-iptables is disabled" - - "WARNING: bridge-nf-call-ip6tables is disabled" CDISpecDirs: description: | List of directories where (Container Device Interface) CDI @@ -5830,13 +6884,13 @@ definitions: - "/var/run/cdi" Containerd: $ref: "#/definitions/ContainerdInfo" - x-nullable: true ContainerdInfo: description: | Information for connecting to the containerd instance that is used by the daemon. This is included for debugging purposes only. type: "object" + x-nullable: true properties: Address: description: "The address of the containerd socket." @@ -5931,55 +6985,27 @@ definitions: List of IP ranges to which nondistributable artifacts can be pushed, using the CIDR syntax [RFC 4632](https://tools.ietf.org/html/4632). - Some images (for example, Windows base images) contain artifacts - whose distribution is restricted by license. When these images are - pushed to a registry, restricted artifacts are not included. - - This configuration override this behavior, and enables the daemon to - push nondistributable artifacts to all registries whose resolved IP - address is within the subnet described by the CIDR syntax. - - This option is useful when pushing images containing - nondistributable artifacts to a registry on an air-gapped network so - hosts on that network can pull the images without connecting to - another server. - - > **Warning**: Nondistributable artifacts typically have restrictions - > on how and where they can be distributed and shared. Only use this - > feature to push artifacts to private registries and ensure that you - > are in compliance with any terms that cover redistributing - > nondistributable artifacts. +


+ > **Deprecated**: Pushing nondistributable artifacts is now always enabled + > and this field is always `null`. This field will be removed in a API v1.49. type: "array" items: type: "string" - example: ["::1/128", "127.0.0.0/8"] + example: [] AllowNondistributableArtifactsHostnames: description: | List of registry hostnames to which nondistributable artifacts can be pushed, using the format `[:]` or `[:]`. - Some images (for example, Windows base images) contain artifacts - whose distribution is restricted by license. When these images are - pushed to a registry, restricted artifacts are not included. - - This configuration override this behavior for the specified - registries. - - This option is useful when pushing images containing - nondistributable artifacts to a registry on an air-gapped network so - hosts on that network can pull the images without connecting to - another server. +


- > **Warning**: Nondistributable artifacts typically have restrictions - > on how and where they can be distributed and shared. Only use this - > feature to push artifacts to private registries and ensure that you - > are in compliance with any terms that cover redistributing - > nondistributable artifacts. + > **Deprecated**: Pushing nondistributable artifacts is now always enabled + > and this field is always `null`. This field will be removed in a API v1.49. type: "array" items: type: "string" - example: ["registry.internal.corp.example.com:3000", "[2001:db8:a0b:12f0::1]:443"] + example: [] InsecureRegistryCIDRs: description: | List of IP ranges of insecure registries, using the CIDR syntax @@ -5987,7 +7013,7 @@ definitions: accept un-encrypted (HTTP) and/or untrusted (HTTPS with certificates from unknown CAs) communication. - By default, local registries (`127.0.0.0/8`) are configured as + By default, local registries (`::1/128` and `127.0.0.0/8`) are configured as insecure. All other registries are secure. Communicating with an insecure registry is not possible if the daemon assumes that registry is secure. @@ -6152,6 +7178,8 @@ definitions: Expected: description: | Commit ID of external tool expected by dockerd as set at build time. + + **Deprecated**: This field is deprecated and will be omitted in a API v1.49. type: "string" example: "2d41c047c83e09a6d61d464906feb2a2f3c52aa4" @@ -6322,7 +7350,7 @@ definitions: description: | The media type of the object this schema refers to. type: "string" - example: "application/vnd.docker.distribution.manifest.v2+json" + example: "application/vnd.oci.image.manifest.v1+json" digest: description: | The digest of the targeted content. @@ -6333,27 +7361,52 @@ definitions: The size in bytes of the blob. type: "integer" format: "int64" - example: 3987495 - # TODO Not yet including these fields for now, as they are nil / omitted in our response. - # urls: - # description: | - # List of URLs from which this object MAY be downloaded. - # type: "array" - # items: - # type: "string" - # format: "uri" - # annotations: - # description: | - # Arbitrary metadata relating to the targeted content. - # type: "object" - # additionalProperties: - # type: "string" - # platform: - # $ref: "#/definitions/OCIPlatform" + example: 424 + urls: + description: |- + List of URLs from which this object MAY be downloaded. + type: "array" + items: + type: "string" + format: "uri" + x-nullable: true + annotations: + description: |- + Arbitrary metadata relating to the targeted content. + type: "object" + x-nullable: true + additionalProperties: + type: "string" + example: + "com.docker.official-images.bashbrew.arch": "amd64" + "org.opencontainers.image.base.digest": "sha256:0d0ef5c914d3ea700147da1bd050c59edb8bb12ca312f3800b29d7c8087eabd8" + "org.opencontainers.image.base.name": "scratch" + "org.opencontainers.image.created": "2025-01-27T00:00:00Z" + "org.opencontainers.image.revision": "9fabb4bad5138435b01857e2fe9363e2dc5f6a79" + "org.opencontainers.image.source": "https://git.launchpad.net/cloud-images/+oci/ubuntu-base" + "org.opencontainers.image.url": "https://hub.docker.com/_/ubuntu" + "org.opencontainers.image.version": "24.04" + data: + type: string + x-nullable: true + description: |- + Data is an embedding of the targeted content. This is encoded as a base64 + string when marshalled to JSON (automatically, by encoding/json). If + present, Data can be used directly to avoid fetching the targeted content. + example: null + platform: + $ref: "#/definitions/OCIPlatform" + artifactType: + description: |- + ArtifactType is the IANA media type of this artifact. + type: "string" + x-nullable: true + example: null OCIPlatform: type: "object" x-go-name: Platform + x-nullable: true description: | Describes the platform which the image in the manifest runs on, as defined in the [OCI Image Index Specification](https://github.com/opencontainers/image-spec/blob/v1.0.1/image-index.md). @@ -6644,6 +7697,120 @@ definitions: additionalProperties: type: "string" + ImageManifestSummary: + x-go-name: "ManifestSummary" + description: | + ImageManifestSummary represents a summary of an image manifest. + type: "object" + required: ["ID", "Descriptor", "Available", "Size", "Kind"] + properties: + ID: + description: | + ID is the content-addressable ID of an image and is the same as the + digest of the image manifest. + type: "string" + example: "sha256:95869fbcf224d947ace8d61d0e931d49e31bb7fc67fffbbe9c3198c33aa8e93f" + Descriptor: + $ref: "#/definitions/OCIDescriptor" + Available: + description: Indicates whether all the child content (image config, layers) is fully available locally. + type: "boolean" + example: true + Size: + type: "object" + x-nullable: false + required: ["Content", "Total"] + properties: + Total: + type: "integer" + format: "int64" + example: 8213251 + description: | + Total is the total size (in bytes) of all the locally present + data (both distributable and non-distributable) that's related to + this manifest and its children. + This equal to the sum of [Content] size AND all the sizes in the + [Size] struct present in the Kind-specific data struct. + For example, for an image kind (Kind == "image") + this would include the size of the image content and unpacked + image snapshots ([Size.Content] + [ImageData.Size.Unpacked]). + Content: + description: | + Content is the size (in bytes) of all the locally present + content in the content store (e.g. image config, layers) + referenced by this manifest and its children. + This only includes blobs in the content store. + type: "integer" + format: "int64" + example: 3987495 + Kind: + type: "string" + example: "image" + enum: + - "image" + - "attestation" + - "unknown" + description: | + The kind of the manifest. + + kind | description + -------------|----------------------------------------------------------- + image | Image manifest that can be used to start a container. + attestation | Attestation manifest produced by the Buildkit builder for a specific image manifest. + ImageData: + description: | + The image data for the image manifest. + This field is only populated when Kind is "image". + type: "object" + x-nullable: true + x-omitempty: true + required: ["Platform", "Containers", "Size", "UnpackedSize"] + properties: + Platform: + $ref: "#/definitions/OCIPlatform" + description: | + OCI platform of the image. This will be the platform specified in the + manifest descriptor from the index/manifest list. + If it's not available, it will be obtained from the image config. + Containers: + description: | + The IDs of the containers that are using this image. + type: "array" + items: + type: "string" + example: ["ede54ee1fda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c7430", "abadbce344c096744d8d6071a90d474d28af8f1034b5ea9fb03c3f4bfc6d005e"] + Size: + type: "object" + x-nullable: false + required: ["Unpacked"] + properties: + Unpacked: + type: "integer" + format: "int64" + example: 3987495 + description: | + Unpacked is the size (in bytes) of the locally unpacked + (uncompressed) image content that's directly usable by the containers + running this image. + It's independent of the distributable content - e.g. + the image might still have an unpacked data that's still used by + some container even when the distributable/compressed content is + already gone. + AttestationData: + description: | + The image data for the attestation manifest. + This field is only populated when Kind is "attestation". + type: "object" + x-nullable: true + x-omitempty: true + required: ["For"] + properties: + For: + description: | + The digest of the image manifest that this attestation is for. + type: "string" + example: "sha256:95869fbcf224d947ace8d61d0e931d49e31bb7fc67fffbbe9c3198c33aa8e93f" + paths: /containers/json: get: @@ -6709,143 +7876,6 @@ paths: type: "array" items: $ref: "#/definitions/ContainerSummary" - examples: - application/json: - - Id: "8dfafdbc3a40" - Names: - - "/boring_feynman" - Image: "ubuntu:latest" - ImageID: "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82" - Command: "echo 1" - Created: 1367854155 - State: "Exited" - Status: "Exit 0" - Ports: - - PrivatePort: 2222 - PublicPort: 3333 - Type: "tcp" - Labels: - com.example.vendor: "Acme" - com.example.license: "GPL" - com.example.version: "1.0" - SizeRw: 12288 - SizeRootFs: 0 - HostConfig: - NetworkMode: "default" - Annotations: - io.kubernetes.docker.type: "container" - NetworkSettings: - Networks: - bridge: - NetworkID: "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812" - EndpointID: "2cdc4edb1ded3631c81f57966563e5c8525b81121bb3706a9a9a3ae102711f3f" - Gateway: "172.17.0.1" - IPAddress: "172.17.0.2" - IPPrefixLen: 16 - IPv6Gateway: "" - GlobalIPv6Address: "" - GlobalIPv6PrefixLen: 0 - MacAddress: "02:42:ac:11:00:02" - Mounts: - - Name: "fac362...80535" - Source: "/data" - Destination: "/data" - Driver: "local" - Mode: "ro,Z" - RW: false - Propagation: "" - - Id: "9cd87474be90" - Names: - - "/coolName" - Image: "ubuntu:latest" - ImageID: "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82" - Command: "echo 222222" - Created: 1367854155 - State: "Exited" - Status: "Exit 0" - Ports: [] - Labels: {} - SizeRw: 12288 - SizeRootFs: 0 - HostConfig: - NetworkMode: "default" - Annotations: - io.kubernetes.docker.type: "container" - io.kubernetes.sandbox.id: "3befe639bed0fd6afdd65fd1fa84506756f59360ec4adc270b0fdac9be22b4d3" - NetworkSettings: - Networks: - bridge: - NetworkID: "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812" - EndpointID: "88eaed7b37b38c2a3f0c4bc796494fdf51b270c2d22656412a2ca5d559a64d7a" - Gateway: "172.17.0.1" - IPAddress: "172.17.0.8" - IPPrefixLen: 16 - IPv6Gateway: "" - GlobalIPv6Address: "" - GlobalIPv6PrefixLen: 0 - MacAddress: "02:42:ac:11:00:08" - Mounts: [] - - Id: "3176a2479c92" - Names: - - "/sleepy_dog" - Image: "ubuntu:latest" - ImageID: "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82" - Command: "echo 3333333333333333" - Created: 1367854154 - State: "Exited" - Status: "Exit 0" - Ports: [] - Labels: {} - SizeRw: 12288 - SizeRootFs: 0 - HostConfig: - NetworkMode: "default" - Annotations: - io.kubernetes.image.id: "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82" - io.kubernetes.image.name: "ubuntu:latest" - NetworkSettings: - Networks: - bridge: - NetworkID: "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812" - EndpointID: "8b27c041c30326d59cd6e6f510d4f8d1d570a228466f956edf7815508f78e30d" - Gateway: "172.17.0.1" - IPAddress: "172.17.0.6" - IPPrefixLen: 16 - IPv6Gateway: "" - GlobalIPv6Address: "" - GlobalIPv6PrefixLen: 0 - MacAddress: "02:42:ac:11:00:06" - Mounts: [] - - Id: "4cb07b47f9fb" - Names: - - "/running_cat" - Image: "ubuntu:latest" - ImageID: "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82" - Command: "echo 444444444444444444444444444444444" - Created: 1367854152 - State: "Exited" - Status: "Exit 0" - Ports: [] - Labels: {} - SizeRw: 12288 - SizeRootFs: 0 - HostConfig: - NetworkMode: "default" - Annotations: - io.kubernetes.config.source: "api" - NetworkSettings: - Networks: - bridge: - NetworkID: "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812" - EndpointID: "d91c7b2f0644403d7ef3095985ea0e2370325cd2332ff3a3225c4247328e66e9" - Gateway: "172.17.0.1" - IPAddress: "172.17.0.5" - IPPrefixLen: 16 - IPv6Gateway: "" - GlobalIPv6Address: "" - GlobalIPv6PrefixLen: 0 - MacAddress: "02:42:ac:11:00:05" - Mounts: [] 400: description: "bad parameter" schema: @@ -7070,238 +8100,7 @@ paths: 200: description: "no error" schema: - type: "object" - title: "ContainerInspectResponse" - properties: - Id: - description: "The ID of the container" - type: "string" - Created: - description: "The time the container was created" - type: "string" - Path: - description: "The path to the command being run" - type: "string" - Args: - description: "The arguments to the command being run" - type: "array" - items: - type: "string" - State: - $ref: "#/definitions/ContainerState" - Image: - description: "The container's image ID" - type: "string" - ResolvConfPath: - type: "string" - HostnamePath: - type: "string" - HostsPath: - type: "string" - LogPath: - type: "string" - Name: - type: "string" - RestartCount: - type: "integer" - Driver: - type: "string" - Platform: - type: "string" - MountLabel: - type: "string" - ProcessLabel: - type: "string" - AppArmorProfile: - type: "string" - ExecIDs: - description: "IDs of exec instances that are running in the container." - type: "array" - items: - type: "string" - x-nullable: true - HostConfig: - $ref: "#/definitions/HostConfig" - GraphDriver: - $ref: "#/definitions/GraphDriverData" - SizeRw: - description: | - The size of files that have been created or changed by this - container. - type: "integer" - format: "int64" - SizeRootFs: - description: "The total size of all the files in this container." - type: "integer" - format: "int64" - Mounts: - type: "array" - items: - $ref: "#/definitions/MountPoint" - Config: - $ref: "#/definitions/ContainerConfig" - NetworkSettings: - $ref: "#/definitions/NetworkSettings" - examples: - application/json: - AppArmorProfile: "" - Args: - - "-c" - - "exit 9" - Config: - AttachStderr: true - AttachStdin: false - AttachStdout: true - Cmd: - - "/bin/sh" - - "-c" - - "exit 9" - Domainname: "" - Env: - - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - Healthcheck: - Test: ["CMD-SHELL", "exit 0"] - Hostname: "ba033ac44011" - Image: "ubuntu" - Labels: - com.example.vendor: "Acme" - com.example.license: "GPL" - com.example.version: "1.0" - MacAddress: "" - NetworkDisabled: false - OpenStdin: false - StdinOnce: false - Tty: false - User: "" - Volumes: - /volumes/data: {} - WorkingDir: "" - StopSignal: "SIGTERM" - StopTimeout: 10 - Created: "2015-01-06T15:47:31.485331387Z" - Driver: "overlay2" - ExecIDs: - - "b35395de42bc8abd327f9dd65d913b9ba28c74d2f0734eeeae84fa1c616a0fca" - - "3fc1232e5cd20c8de182ed81178503dc6437f4e7ef12b52cc5e8de020652f1c4" - HostConfig: - MaximumIOps: 0 - MaximumIOBps: 0 - BlkioWeight: 0 - BlkioWeightDevice: - - {} - BlkioDeviceReadBps: - - {} - BlkioDeviceWriteBps: - - {} - BlkioDeviceReadIOps: - - {} - BlkioDeviceWriteIOps: - - {} - ContainerIDFile: "" - CpusetCpus: "" - CpusetMems: "" - CpuPercent: 80 - CpuShares: 0 - CpuPeriod: 100000 - CpuRealtimePeriod: 1000000 - CpuRealtimeRuntime: 10000 - Devices: [] - DeviceRequests: - - Driver: "nvidia" - Count: -1 - DeviceIDs": ["0", "1", "GPU-fef8089b-4820-abfc-e83e-94318197576e"] - Capabilities: [["gpu", "nvidia", "compute"]] - Options: - property1: "string" - property2: "string" - IpcMode: "" - Memory: 0 - MemorySwap: 0 - MemoryReservation: 0 - OomKillDisable: false - OomScoreAdj: 500 - NetworkMode: "bridge" - PidMode: "" - PortBindings: {} - Privileged: false - ReadonlyRootfs: false - PublishAllPorts: false - RestartPolicy: - MaximumRetryCount: 2 - Name: "on-failure" - LogConfig: - Type: "json-file" - Sysctls: - net.ipv4.ip_forward: "1" - Ulimits: - - {} - VolumeDriver: "" - ShmSize: 67108864 - HostnamePath: "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hostname" - HostsPath: "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hosts" - LogPath: "/var/lib/docker/containers/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b-json.log" - Id: "ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39" - Image: "04c5d3b7b0656168630d3ba35d8889bd0e9caafcaeb3004d2bfbc47e7c5d35d2" - MountLabel: "" - Name: "/boring_euclid" - NetworkSettings: - Bridge: "" - SandboxID: "" - HairpinMode: false - LinkLocalIPv6Address: "" - LinkLocalIPv6PrefixLen: 0 - SandboxKey: "" - EndpointID: "" - Gateway: "" - GlobalIPv6Address: "" - GlobalIPv6PrefixLen: 0 - IPAddress: "" - IPPrefixLen: 0 - IPv6Gateway: "" - MacAddress: "" - Networks: - bridge: - NetworkID: "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812" - EndpointID: "7587b82f0dada3656fda26588aee72630c6fab1536d36e394b2bfbcf898c971d" - Gateway: "172.17.0.1" - IPAddress: "172.17.0.2" - IPPrefixLen: 16 - IPv6Gateway: "" - GlobalIPv6Address: "" - GlobalIPv6PrefixLen: 0 - MacAddress: "02:42:ac:12:00:02" - Path: "/bin/sh" - ProcessLabel: "" - ResolvConfPath: "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/resolv.conf" - RestartCount: 1 - State: - Error: "" - ExitCode: 9 - FinishedAt: "2015-01-06T15:47:32.080254511Z" - Health: - Status: "healthy" - FailingStreak: 0 - Log: - - Start: "2019-12-22T10:59:05.6385933Z" - End: "2019-12-22T10:59:05.8078452Z" - ExitCode: 0 - Output: "" - OOMKilled: false - Dead: false - Paused: false - Pid: 0 - Restarting: false - Running: true - StartedAt: "2015-01-06T15:47:32.072697474Z" - Status: "running" - Mounts: - - Name: "fac362...80535" - Source: "/data" - Destination: "/data" - Driver: "local" - Mode: "ro,Z" - RW: false - Propagation: "" + $ref: "#/definitions/ContainerInspectResponse" 404: description: "no such container" schema: @@ -7336,54 +8135,7 @@ paths: 200: description: "no error" schema: - type: "object" - title: "ContainerTopResponse" - description: "OK response to ContainerTop operation" - properties: - Titles: - description: "The ps column titles" - type: "array" - items: - type: "string" - Processes: - description: | - Each process running in the container, where each is process - is an array of values corresponding to the titles. - type: "array" - items: - type: "array" - items: - type: "string" - examples: - application/json: - Titles: - - "UID" - - "PID" - - "PPID" - - "C" - - "STIME" - - "TTY" - - "TIME" - - "CMD" - Processes: - - - - "root" - - "13642" - - "882" - - "0" - - "17:03" - - "pts/0" - - "00:00:00" - - "/bin/bash" - - - - "root" - - "13735" - - "13642" - - "0" - - "17:06" - - "pts/0" - - "00:00:00" - - "sleep 10" + $ref: "#/definitions/ContainerTopResponse" 404: description: "no such container" schema: @@ -7585,7 +8337,7 @@ paths: * Memory usage % = `(used_memory / available_memory) * 100.0` * cpu_delta = `cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage` * system_cpu_delta = `cpu_stats.system_cpu_usage - precpu_stats.system_cpu_usage` - * number_cpus = `lenght(cpu_stats.cpu_usage.percpu_usage)` or `cpu_stats.online_cpus` + * number_cpus = `length(cpu_stats.cpu_usage.percpu_usage)` or `cpu_stats.online_cpus` * CPU usage % = `(cpu_delta / system_cpu_delta) * number_cpus * 100.0` operationId: "ContainerStats" produces: ["application/json"] @@ -7593,99 +8345,7 @@ paths: 200: description: "no error" schema: - type: "object" - examples: - application/json: - read: "2015-01-08T22:57:31.547920715Z" - pids_stats: - current: 3 - networks: - eth0: - rx_bytes: 5338 - rx_dropped: 0 - rx_errors: 0 - rx_packets: 36 - tx_bytes: 648 - tx_dropped: 0 - tx_errors: 0 - tx_packets: 8 - eth5: - rx_bytes: 4641 - rx_dropped: 0 - rx_errors: 0 - rx_packets: 26 - tx_bytes: 690 - tx_dropped: 0 - tx_errors: 0 - tx_packets: 9 - memory_stats: - stats: - total_pgmajfault: 0 - cache: 0 - mapped_file: 0 - total_inactive_file: 0 - pgpgout: 414 - rss: 6537216 - total_mapped_file: 0 - writeback: 0 - unevictable: 0 - pgpgin: 477 - total_unevictable: 0 - pgmajfault: 0 - total_rss: 6537216 - total_rss_huge: 6291456 - total_writeback: 0 - total_inactive_anon: 0 - rss_huge: 6291456 - hierarchical_memory_limit: 67108864 - total_pgfault: 964 - total_active_file: 0 - active_anon: 6537216 - total_active_anon: 6537216 - total_pgpgout: 414 - total_cache: 0 - inactive_anon: 0 - active_file: 0 - pgfault: 964 - inactive_file: 0 - total_pgpgin: 477 - max_usage: 6651904 - usage: 6537216 - failcnt: 0 - limit: 67108864 - blkio_stats: {} - cpu_stats: - cpu_usage: - percpu_usage: - - 8646879 - - 24472255 - - 36438778 - - 30657443 - usage_in_usermode: 50000000 - total_usage: 100215355 - usage_in_kernelmode: 30000000 - system_cpu_usage: 739306590000000 - online_cpus: 4 - throttling_data: - periods: 0 - throttled_periods: 0 - throttled_time: 0 - precpu_stats: - cpu_usage: - percpu_usage: - - 8646879 - - 24350896 - - 36438778 - - 30657443 - usage_in_usermode: 50000000 - total_usage: 100093996 - usage_in_kernelmode: 30000000 - system_cpu_usage: 9492140000000 - online_cpus: 4 - throttling_data: - periods: 0 - throttled_periods: 0 - throttled_time: 0 + $ref: "#/definitions/ContainerStatsResponse" 404: description: "no such container" schema: @@ -7749,10 +8409,12 @@ paths: type: "string" - name: "h" in: "query" + required: true description: "Height of the TTY session in characters" type: "integer" - name: "w" in: "query" + required: true description: "Width of the TTY session in characters" type: "integer" tags: ["Container"] @@ -7914,14 +8576,7 @@ paths: 200: description: "The container has been updated." schema: - type: "object" - title: "ContainerUpdateResponse" - description: "OK response to ContainerUpdate operation" - properties: - Warnings: - type: "array" - items: - type: "string" + $ref: "#/definitions/ContainerUpdateResponse" 404: description: "no such container" schema: @@ -8622,6 +9277,11 @@ paths: description: "Show digest information as a `RepoDigests` field on each image." type: "boolean" default: false + - name: "manifests" + in: "query" + description: "Include `Manifests` in the image summary." + type: "boolean" + default: false tags: ["Image"] /build: post: @@ -8823,10 +9483,29 @@ paths: operationId: "BuildPrune" parameters: - name: "keep-storage" + in: "query" + description: | + Amount of disk space in bytes to keep for cache + + > **Deprecated**: This parameter is deprecated and has been renamed to "reserved-space". + > It is kept for backward compatibility and will be removed in API v1.49. + type: "integer" + format: "int64" + - name: "reserved-space" in: "query" description: "Amount of disk space in bytes to keep for cache" type: "integer" format: "int64" + - name: "max-used-space" + in: "query" + description: "Maximum amount of disk space allowed to keep for cache" + type: "integer" + format: "int64" + - name: "min-free-space" + in: "query" + description: "Target amount of free disk space after pruning" + type: "integer" + format: "int64" - name: "all" in: "query" type: "boolean" @@ -8893,7 +9572,13 @@ paths: parameters: - name: "fromImage" in: "query" - description: "Name of the image to pull. The name may include a tag or digest. This parameter may only be used when pulling an image. The pull is cancelled if the HTTP connection is closed." + description: | + Name of the image to pull. If the name includes a tag or digest, specific behavior applies: + + - If only `fromImage` includes a tag, that tag is used. + - If both `fromImage` and `tag` are provided, `tag` takes precedence. + - If `fromImage` includes a digest, the image is pulled by digest, and `tag` is ignored. + - If neither a tag nor digest is specified, all tags are pulled. type: "string" - name: "fromSrc" in: "query" @@ -8987,6 +9672,12 @@ paths: description: "Image name or id" type: "string" required: true + - name: "manifests" + in: "query" + description: "Include Manifests in the image summary." + type: "boolean" + default: false + required: false tags: ["Image"] /images/{name}/history: get: @@ -9065,6 +9756,20 @@ paths: description: "Image name or ID" type: "string" required: true + - name: "platform" + type: "string" + in: "query" + description: | + JSON-encoded OCI platform to select the platform-variant. + If omitted, it defaults to any locally available platform, + prioritizing the daemon's host platform. + + If the daemon provides a multi-platform image store, this selects + the platform-variant to show the history for. If the image is + a single-platform image, or if the multi-platform image does not + provide a variant matching the given platform, an error is returned. + + Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}` tags: ["Image"] /images/{name}/push: post: @@ -9094,13 +9799,37 @@ paths: parameters: - name: "name" in: "path" - description: "Image name or ID." + description: | + Name of the image to push. For example, `registry.example.com/myimage`. + The image must be present in the local image store with the same name. + + The name should be provided without tag; if a tag is provided, it + is ignored. For example, `registry.example.com/myimage:latest` is + considered equivalent to `registry.example.com/myimage`. + + Use the `tag` parameter to specify the tag to push. type: "string" required: true - name: "tag" in: "query" - description: "The tag to associate with the image on the registry." + description: | + Tag of the image to push. For example, `latest`. If no tag is provided, + all tags of the given image that are present in the local image store + are pushed. type: "string" + - name: "platform" + type: "string" + in: "query" + description: | + JSON-encoded OCI platform to select the platform-variant to push. + If not provided, all available variants will attempt to be pushed. + + If the daemon provides a multi-platform image store, this selects + the platform-variant to push to the registry. If the image is + a single-platform image, or if the multi-platform image does not + provide a variant matching the given platform, an error is returned. + + Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}` - name: "X-Registry-Auth" in: "header" description: | @@ -9110,11 +9839,6 @@ paths: details. type: "string" required: true - - name: "platform" - in: "query" - description: "Select a platform-specific manifest to be pushed. OCI platform (JSON encoded)" - type: "string" - x-nullable: true tags: ["Image"] /images/{name}/tag: post: @@ -9410,7 +10134,7 @@ paths: type: "string" example: "OK" headers: - API-Version: + Api-Version: type: "string" description: "Max API Version the server supports" Builder-Version: @@ -9466,7 +10190,7 @@ paths: type: "string" example: "(empty)" headers: - API-Version: + Api-Version: type: "string" description: "Max API Version the server supports" Builder-Version: @@ -9505,7 +10229,7 @@ paths: 201: description: "no error" schema: - $ref: "#/definitions/IdResponse" + $ref: "#/definitions/IDResponse" 404: description: "no such container" schema: @@ -9799,7 +10523,16 @@ paths: description: "Image name or ID" type: "string" required: true - tags: ["Image"] + - name: "platform" + type: "string" + in: "query" + description: | + JSON encoded OCI platform describing a platform which will be used + to select a platform-specific image to be saved if the image is + multi-platform. + If not provided, the full multi-platform image will be saved. + + Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}` /images/get: get: summary: "Export several images" @@ -9866,6 +10599,16 @@ paths: description: "Suppress progress details during load." type: "boolean" default: false + - name: "platform" + type: "string" + in: "query" + description: | + JSON encoded OCI platform describing a platform which will be used + to select a platform-specific image to be load if the image is + multi-platform. + If not provided, the full multi-platform image will be loaded. + + Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}` tags: ["Image"] /containers/{id}/exec: post: @@ -9880,7 +10623,7 @@ paths: 201: description: "no error" schema: - $ref: "#/definitions/IdResponse" + $ref: "#/definitions/IDResponse" 404: description: "no such container" schema: @@ -9922,6 +10665,7 @@ paths: items: type: "integer" minimum: 0 + example: [80, 64] DetachKeys: type: "string" description: | @@ -10008,9 +10752,11 @@ paths: Detach: type: "boolean" description: "Detach from the command." + example: false Tty: type: "boolean" description: "Allocate a pseudo-TTY." + example: true ConsoleSize: type: "array" description: "Initial console size, as an `[height, width]` array." @@ -10020,10 +10766,7 @@ paths: items: type: "integer" minimum: 0 - example: - Detach: false - Tty: true - ConsoleSize: [80, 64] + example: [80, 64] - name: "id" in: "path" description: "Exec instance ID" @@ -10060,10 +10803,12 @@ paths: type: "string" - name: "h" in: "query" + required: true description: "Height of the TTY session in characters" type: "integer" - name: "w" in: "query" + required: true description: "Width of the TTY session in characters" type: "integer" tags: ["Exec"] @@ -10377,6 +11122,7 @@ paths: Created: "2016-10-19T06:21:00.416543526Z" Scope: "local" Driver: "bridge" + EnableIPv4: true EnableIPv6: false Internal: false Attachable: false @@ -10398,6 +11144,7 @@ paths: Created: "0001-01-01T00:00:00Z" Scope: "local" Driver: "null" + EnableIPv4: false EnableIPv6: false Internal: false Attachable: false @@ -10412,6 +11159,7 @@ paths: Created: "0001-01-01T00:00:00Z" Scope: "local" Driver: "host" + EnableIPv4: false EnableIPv6: false Internal: false Attachable: false @@ -10597,6 +11345,10 @@ paths: IPAM: description: "Optional custom IP scheme for the network." $ref: "#/definitions/IPAM" + EnableIPv4: + description: "Enable IPv4 on the network." + type: "boolean" + example: true EnableIPv6: description: "Enable IPv6 on the network." type: "boolean" @@ -10674,6 +11426,7 @@ paths: IPv4Address: "172.24.56.89" IPv6Address: "2001:db8::5689" MacAddress: "02:42:ac:12:05:02" + Priority: 100 tags: ["Network"] /networks/{id}/disconnect: @@ -11479,6 +12232,7 @@ paths: example: ListenAddr: "0.0.0.0:2377" AdvertiseAddr: "192.168.1.1:2377" + DataPathAddr: "192.168.1.1" RemoteAddrs: - "node1:2377" JoinToken: "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2" @@ -12349,7 +13103,7 @@ paths: 201: description: "no error" schema: - $ref: "#/definitions/IdResponse" + $ref: "#/definitions/IDResponse" 409: description: "name conflicts with an existing object" schema: @@ -12556,7 +13310,7 @@ paths: 201: description: "no error" schema: - $ref: "#/definitions/IdResponse" + $ref: "#/definitions/IDResponse" 409: description: "name conflicts with an existing object" schema: diff --git a/vendor/github.com/docker/docker/api/types/client.go b/vendor/github.com/docker/docker/api/types/client.go index df791f02a..dce8260f3 100644 --- a/vendor/github.com/docker/docker/api/types/client.go +++ b/vendor/github.com/docker/docker/api/types/client.go @@ -11,7 +11,7 @@ import ( "github.com/docker/docker/api/types/registry" ) -// NewHijackedResponse intializes a HijackedResponse type +// NewHijackedResponse initializes a [HijackedResponse] type. func NewHijackedResponse(conn net.Conn, mediaType string) HijackedResponse { return HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn), mediaType: mediaType} } @@ -129,14 +129,6 @@ type ImageBuildResponse struct { OSType string } -// RequestPrivilegeFunc is a function interface that -// clients can supply to retry operations after -// getting an authorization error. -// This function returns the registry authentication -// header value in base 64 format, or an error -// if the privilege request fails. -type RequestPrivilegeFunc func(context.Context) (string, error) - // NodeListOptions holds parameters to list nodes with. type NodeListOptions struct { Filters filters.Args @@ -235,11 +227,18 @@ type PluginDisableOptions struct { // PluginInstallOptions holds parameters to install a plugin. type PluginInstallOptions struct { - Disabled bool - AcceptAllPermissions bool - RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry - RemoteRef string // RemoteRef is the plugin name on the registry - PrivilegeFunc RequestPrivilegeFunc + Disabled bool + AcceptAllPermissions bool + RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry + RemoteRef string // RemoteRef is the plugin name on the registry + + // PrivilegeFunc is a function that clients can supply to retry operations + // after getting an authorization error. This function returns the registry + // authentication header value in base64 encoded format, or an error if the + // privilege request fails. + // + // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. + PrivilegeFunc func(context.Context) (string, error) AcceptPermissionsFunc func(context.Context, PluginPrivileges) (bool, error) Args []string } diff --git a/vendor/github.com/docker/docker/api/types/id_response.go b/vendor/github.com/docker/docker/api/types/common/id_response.go similarity index 87% rename from vendor/github.com/docker/docker/api/types/id_response.go rename to vendor/github.com/docker/docker/api/types/common/id_response.go index 7592d2f8b..22e8c60a4 100644 --- a/vendor/github.com/docker/docker/api/types/id_response.go +++ b/vendor/github.com/docker/docker/api/types/common/id_response.go @@ -1,10 +1,10 @@ -package types +package common // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command // IDResponse Response to an API call that returns just an Id -// swagger:model IdResponse +// swagger:model IDResponse type IDResponse struct { // The id of the newly created object. diff --git a/vendor/github.com/docker/docker/api/types/container/commit.go b/vendor/github.com/docker/docker/api/types/container/commit.go new file mode 100644 index 000000000..6fd1b0ead --- /dev/null +++ b/vendor/github.com/docker/docker/api/types/container/commit.go @@ -0,0 +1,7 @@ +package container + +import "github.com/docker/docker/api/types/common" + +// CommitResponse response for the commit API call, containing the ID of the +// image that was produced. +type CommitResponse = common.IDResponse diff --git a/vendor/github.com/docker/docker/api/types/container/container.go b/vendor/github.com/docker/docker/api/types/container/container.go index 711af12c9..65fabbf42 100644 --- a/vendor/github.com/docker/docker/api/types/container/container.go +++ b/vendor/github.com/docker/docker/api/types/container/container.go @@ -4,8 +4,22 @@ import ( "io" "os" "time" + + "github.com/docker/docker/api/types/mount" + "github.com/docker/docker/api/types/storage" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) +// ContainerUpdateOKBody OK response to ContainerUpdate operation +// +// Deprecated: use [UpdateResponse]. This alias will be removed in the next release. +type ContainerUpdateOKBody = UpdateResponse + +// ContainerTopOKBody OK response to ContainerTop operation +// +// Deprecated: use [TopResponse]. This alias will be removed in the next release. +type ContainerTopOKBody = TopResponse + // PruneReport contains the response for Engine API: // POST "/containers/prune" type PruneReport struct { @@ -42,3 +56,133 @@ type StatsResponseReader struct { Body io.ReadCloser `json:"body"` OSType string `json:"ostype"` } + +// MountPoint represents a mount point configuration inside the container. +// This is used for reporting the mountpoints in use by a container. +type MountPoint struct { + // Type is the type of mount, see `Type` definitions in + // github.com/docker/docker/api/types/mount.Type + Type mount.Type `json:",omitempty"` + + // Name is the name reference to the underlying data defined by `Source` + // e.g., the volume name. + Name string `json:",omitempty"` + + // Source is the source location of the mount. + // + // For volumes, this contains the storage location of the volume (within + // `/var/lib/docker/volumes/`). For bind-mounts, and `npipe`, this contains + // the source (host) part of the bind-mount. For `tmpfs` mount points, this + // field is empty. + Source string + + // Destination is the path relative to the container root (`/`) where the + // Source is mounted inside the container. + Destination string + + // Driver is the volume driver used to create the volume (if it is a volume). + Driver string `json:",omitempty"` + + // Mode is a comma separated list of options supplied by the user when + // creating the bind/volume mount. + // + // The default is platform-specific (`"z"` on Linux, empty on Windows). + Mode string + + // RW indicates whether the mount is mounted writable (read-write). + RW bool + + // Propagation describes how mounts are propagated from the host into the + // mount point, and vice-versa. Refer to the Linux kernel documentation + // for details: + // https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt + // + // This field is not used on Windows. + Propagation mount.Propagation +} + +// State stores container's running state +// it's part of ContainerJSONBase and returned by "inspect" command +type State struct { + Status string // String representation of the container state. Can be one of "created", "running", "paused", "restarting", "removing", "exited", or "dead" + Running bool + Paused bool + Restarting bool + OOMKilled bool + Dead bool + Pid int + ExitCode int + Error string + StartedAt string + FinishedAt string + Health *Health `json:",omitempty"` +} + +// Summary contains response of Engine API: +// GET "/containers/json" +type Summary struct { + ID string `json:"Id"` + Names []string + Image string + ImageID string + ImageManifestDescriptor *ocispec.Descriptor `json:"ImageManifestDescriptor,omitempty"` + Command string + Created int64 + Ports []Port + SizeRw int64 `json:",omitempty"` + SizeRootFs int64 `json:",omitempty"` + Labels map[string]string + State string + Status string + HostConfig struct { + NetworkMode string `json:",omitempty"` + Annotations map[string]string `json:",omitempty"` + } + NetworkSettings *NetworkSettingsSummary + Mounts []MountPoint +} + +// ContainerJSONBase contains response of Engine API GET "/containers/{name:.*}/json" +// for API version 1.18 and older. +// +// TODO(thaJeztah): combine ContainerJSONBase and InspectResponse into a single struct. +// The split between ContainerJSONBase (ContainerJSONBase) and InspectResponse (InspectResponse) +// was done in commit 6deaa58ba5f051039643cedceee97c8695e2af74 (https://github.com/moby/moby/pull/13675). +// ContainerJSONBase contained all fields for API < 1.19, and InspectResponse +// held fields that were added in API 1.19 and up. Given that the minimum +// supported API version is now 1.24, we no longer use the separate type. +type ContainerJSONBase struct { + ID string `json:"Id"` + Created string + Path string + Args []string + State *State + Image string + ResolvConfPath string + HostnamePath string + HostsPath string + LogPath string + Name string + RestartCount int + Driver string + Platform string + MountLabel string + ProcessLabel string + AppArmorProfile string + ExecIDs []string + HostConfig *HostConfig + GraphDriver storage.DriverData + SizeRw *int64 `json:",omitempty"` + SizeRootFs *int64 `json:",omitempty"` +} + +// InspectResponse is the response for the GET "/containers/{name:.*}/json" +// endpoint. +type InspectResponse struct { + *ContainerJSONBase + Mounts []MountPoint + Config *Config + NetworkSettings *NetworkSettings + // ImageManifestDescriptor is the descriptor of a platform-specific manifest of the image used to create the container. + ImageManifestDescriptor *ocispec.Descriptor `json:"ImageManifestDescriptor,omitempty"` +} diff --git a/vendor/github.com/docker/docker/api/types/container/container_top.go b/vendor/github.com/docker/docker/api/types/container/container_top.go deleted file mode 100644 index 63381da36..000000000 --- a/vendor/github.com/docker/docker/api/types/container/container_top.go +++ /dev/null @@ -1,22 +0,0 @@ -package container // import "github.com/docker/docker/api/types/container" - -// ---------------------------------------------------------------------------- -// Code generated by `swagger generate operation`. DO NOT EDIT. -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -// ContainerTopOKBody OK response to ContainerTop operation -// swagger:model ContainerTopOKBody -type ContainerTopOKBody struct { - - // Each process running in the container, where each is process - // is an array of values corresponding to the titles. - // - // Required: true - Processes [][]string `json:"Processes"` - - // The ps column titles - // Required: true - Titles []string `json:"Titles"` -} diff --git a/vendor/github.com/docker/docker/api/types/container/container_update.go b/vendor/github.com/docker/docker/api/types/container/container_update.go deleted file mode 100644 index c10f175ea..000000000 --- a/vendor/github.com/docker/docker/api/types/container/container_update.go +++ /dev/null @@ -1,16 +0,0 @@ -package container // import "github.com/docker/docker/api/types/container" - -// ---------------------------------------------------------------------------- -// Code generated by `swagger generate operation`. DO NOT EDIT. -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -// ContainerUpdateOKBody OK response to ContainerUpdate operation -// swagger:model ContainerUpdateOKBody -type ContainerUpdateOKBody struct { - - // warnings - // Required: true - Warnings []string `json:"Warnings"` -} diff --git a/vendor/github.com/docker/docker/api/types/container/exec.go b/vendor/github.com/docker/docker/api/types/container/exec.go index 96093eb5c..f4b22376e 100644 --- a/vendor/github.com/docker/docker/api/types/container/exec.go +++ b/vendor/github.com/docker/docker/api/types/container/exec.go @@ -1,5 +1,13 @@ package container +import "github.com/docker/docker/api/types/common" + +// ExecCreateResponse is the response for a successful exec-create request. +// It holds the ID of the exec that was created. +// +// TODO(thaJeztah): make this a distinct type. +type ExecCreateResponse = common.IDResponse + // ExecOptions is a small subset of the Config struct that holds the configuration // for the exec feature of docker. type ExecOptions struct { diff --git a/vendor/github.com/docker/docker/api/types/container/health.go b/vendor/github.com/docker/docker/api/types/container/health.go new file mode 100644 index 000000000..93663746f --- /dev/null +++ b/vendor/github.com/docker/docker/api/types/container/health.go @@ -0,0 +1,26 @@ +package container + +import "time" + +// Health states +const ( + NoHealthcheck = "none" // Indicates there is no healthcheck + Starting = "starting" // Starting indicates that the container is not yet ready + Healthy = "healthy" // Healthy indicates that the container is running correctly + Unhealthy = "unhealthy" // Unhealthy indicates that the container has a problem +) + +// Health stores information about the container's healthcheck results +type Health struct { + Status string // Status is one of [Starting], [Healthy] or [Unhealthy]. + FailingStreak int // FailingStreak is the number of consecutive failures + Log []*HealthcheckResult // Log contains the last few results (oldest first) +} + +// HealthcheckResult stores information about a single run of a healthcheck probe +type HealthcheckResult struct { + Start time.Time // Start is the time this check started + End time.Time // End is the time this check ended + ExitCode int // ExitCode meanings: 0=healthy, 1=unhealthy, 2=reserved (considered unhealthy), else=error running probe + Output string // Output from last check +} diff --git a/vendor/github.com/docker/docker/api/types/container/hostconfig.go b/vendor/github.com/docker/docker/api/types/container/hostconfig.go index 727da8839..83198305e 100644 --- a/vendor/github.com/docker/docker/api/types/container/hostconfig.go +++ b/vendor/github.com/docker/docker/api/types/container/hostconfig.go @@ -1,6 +1,7 @@ package container // import "github.com/docker/docker/api/types/container" import ( + "errors" "fmt" "strings" @@ -9,7 +10,7 @@ import ( "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/strslice" "github.com/docker/go-connections/nat" - units "github.com/docker/go-units" + "github.com/docker/go-units" ) // CgroupnsMode represents the cgroup namespace mode of the container @@ -325,12 +326,12 @@ func ValidateRestartPolicy(policy RestartPolicy) error { if policy.MaximumRetryCount < 0 { msg += " and cannot be negative" } - return &errInvalidParameter{fmt.Errorf(msg)} + return &errInvalidParameter{errors.New(msg)} } return nil case RestartPolicyOnFailure: if policy.MaximumRetryCount < 0 { - return &errInvalidParameter{fmt.Errorf("invalid restart policy: maximum retry count cannot be negative")} + return &errInvalidParameter{errors.New("invalid restart policy: maximum retry count cannot be negative")} } return nil case "": diff --git a/vendor/github.com/docker/docker/api/types/container/network_settings.go b/vendor/github.com/docker/docker/api/types/container/network_settings.go new file mode 100644 index 000000000..afec0e543 --- /dev/null +++ b/vendor/github.com/docker/docker/api/types/container/network_settings.go @@ -0,0 +1,56 @@ +package container + +import ( + "github.com/docker/docker/api/types/network" + "github.com/docker/go-connections/nat" +) + +// NetworkSettings exposes the network settings in the api +type NetworkSettings struct { + NetworkSettingsBase + DefaultNetworkSettings + Networks map[string]*network.EndpointSettings +} + +// NetworkSettingsBase holds networking state for a container when inspecting it. +type NetworkSettingsBase struct { + Bridge string // Bridge contains the name of the default bridge interface iff it was set through the daemon --bridge flag. + SandboxID string // SandboxID uniquely represents a container's network stack + SandboxKey string // SandboxKey identifies the sandbox + Ports nat.PortMap // Ports is a collection of PortBinding indexed by Port + + // HairpinMode specifies if hairpin NAT should be enabled on the virtual interface + // + // Deprecated: This field is never set and will be removed in a future release. + HairpinMode bool + // LinkLocalIPv6Address is an IPv6 unicast address using the link-local prefix + // + // Deprecated: This field is never set and will be removed in a future release. + LinkLocalIPv6Address string + // LinkLocalIPv6PrefixLen is the prefix length of an IPv6 unicast address + // + // Deprecated: This field is never set and will be removed in a future release. + LinkLocalIPv6PrefixLen int + SecondaryIPAddresses []network.Address // Deprecated: This field is never set and will be removed in a future release. + SecondaryIPv6Addresses []network.Address // Deprecated: This field is never set and will be removed in a future release. +} + +// DefaultNetworkSettings holds network information +// during the 2 release deprecation period. +// It will be removed in Docker 1.11. +type DefaultNetworkSettings struct { + EndpointID string // EndpointID uniquely represents a service endpoint in a Sandbox + Gateway string // Gateway holds the gateway address for the network + GlobalIPv6Address string // GlobalIPv6Address holds network's global IPv6 address + GlobalIPv6PrefixLen int // GlobalIPv6PrefixLen represents mask length of network's global IPv6 address + IPAddress string // IPAddress holds the IPv4 address for the network + IPPrefixLen int // IPPrefixLen represents mask length of network's IPv4 address + IPv6Gateway string // IPv6Gateway holds gateway address specific for IPv6 + MacAddress string // MacAddress holds the MAC address for the network +} + +// NetworkSettingsSummary provides a summary of container's networks +// in /containers/json +type NetworkSettingsSummary struct { + Networks map[string]*network.EndpointSettings +} diff --git a/vendor/github.com/docker/docker/api/types/port.go b/vendor/github.com/docker/docker/api/types/container/port.go similarity index 96% rename from vendor/github.com/docker/docker/api/types/port.go rename to vendor/github.com/docker/docker/api/types/container/port.go index d91234744..895043cfe 100644 --- a/vendor/github.com/docker/docker/api/types/port.go +++ b/vendor/github.com/docker/docker/api/types/container/port.go @@ -1,4 +1,4 @@ -package types +package container // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command diff --git a/vendor/github.com/docker/docker/api/types/container/stats.go b/vendor/github.com/docker/docker/api/types/container/stats.go index 3b3fb131a..3bfeb4849 100644 --- a/vendor/github.com/docker/docker/api/types/container/stats.go +++ b/vendor/github.com/docker/docker/api/types/container/stats.go @@ -148,7 +148,15 @@ type PidsStats struct { } // Stats is Ultimate struct aggregating all types of stats of one container -type Stats struct { +// +// Deprecated: use [StatsResponse] instead. This type will be removed in the next release. +type Stats = StatsResponse + +// StatsResponse aggregates all types of stats of one container. +type StatsResponse struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + // Common stats Read time.Time `json:"read"` PreRead time.Time `json:"preread"` @@ -162,20 +170,8 @@ type Stats struct { StorageStats StorageStats `json:"storage_stats,omitempty"` // Shared stats - CPUStats CPUStats `json:"cpu_stats,omitempty"` - PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous" - MemoryStats MemoryStats `json:"memory_stats,omitempty"` -} - -// StatsResponse is newly used Networks. -// -// TODO(thaJeztah): unify with [Stats]. This wrapper was to account for pre-api v1.21 changes, see https://github.com/moby/moby/commit/d3379946ec96fb6163cb8c4517d7d5a067045801 -type StatsResponse struct { - Stats - - Name string `json:"name,omitempty"` - ID string `json:"id,omitempty"` - - // Networks request version >=1.21 - Networks map[string]NetworkStats `json:"networks,omitempty"` + CPUStats CPUStats `json:"cpu_stats,omitempty"` + PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous" + MemoryStats MemoryStats `json:"memory_stats,omitempty"` + Networks map[string]NetworkStats `json:"networks,omitempty"` } diff --git a/vendor/github.com/docker/docker/api/types/container/top_response.go b/vendor/github.com/docker/docker/api/types/container/top_response.go new file mode 100644 index 000000000..b4bae5ef0 --- /dev/null +++ b/vendor/github.com/docker/docker/api/types/container/top_response.go @@ -0,0 +1,18 @@ +package container + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +// TopResponse ContainerTopResponse +// +// Container "top" response. +// swagger:model TopResponse +type TopResponse struct { + + // Each process running in the container, where each process + // is an array of values corresponding to the titles. + Processes [][]string `json:"Processes"` + + // The ps column titles + Titles []string `json:"Titles"` +} diff --git a/vendor/github.com/docker/docker/api/types/container/update_response.go b/vendor/github.com/docker/docker/api/types/container/update_response.go new file mode 100644 index 000000000..e2b5bf5ac --- /dev/null +++ b/vendor/github.com/docker/docker/api/types/container/update_response.go @@ -0,0 +1,14 @@ +package container + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +// UpdateResponse ContainerUpdateResponse +// +// Response for a successful container-update. +// swagger:model UpdateResponse +type UpdateResponse struct { + + // Warnings encountered when updating the container. + Warnings []string `json:"Warnings"` +} diff --git a/vendor/github.com/docker/docker/api/types/filters/errors.go b/vendor/github.com/docker/docker/api/types/filters/errors.go index f52f69440..b8a690d67 100644 --- a/vendor/github.com/docker/docker/api/types/filters/errors.go +++ b/vendor/github.com/docker/docker/api/types/filters/errors.go @@ -22,16 +22,3 @@ func (e invalidFilter) Error() string { // InvalidParameter marks this error as ErrInvalidParameter func (e invalidFilter) InvalidParameter() {} - -// unreachableCode is an error indicating that the code path was not expected to be reached. -type unreachableCode struct { - Filter string - Value []string -} - -// System marks this error as ErrSystem -func (e unreachableCode) System() {} - -func (e unreachableCode) Error() string { - return fmt.Sprintf("unreachable code reached for filter: %q with values: %s", e.Filter, e.Value) -} diff --git a/vendor/github.com/docker/docker/api/types/filters/parse.go b/vendor/github.com/docker/docker/api/types/filters/parse.go index 0c39ab5f1..2085ff38f 100644 --- a/vendor/github.com/docker/docker/api/types/filters/parse.go +++ b/vendor/github.com/docker/docker/api/types/filters/parse.go @@ -196,11 +196,10 @@ func (args Args) Match(field, source string) bool { } // GetBoolOrDefault returns a boolean value of the key if the key is present -// and is intepretable as a boolean value. Otherwise the default value is returned. +// and is interpretable as a boolean value. Otherwise the default value is returned. // Error is not nil only if the filter values are not valid boolean or are conflicting. func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) { fieldValues, ok := args.fields[key] - if !ok { return defaultValue, nil } @@ -211,20 +210,11 @@ func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) { isFalse := fieldValues["0"] || fieldValues["false"] isTrue := fieldValues["1"] || fieldValues["true"] - - conflicting := isFalse && isTrue - invalid := !isFalse && !isTrue - - if conflicting || invalid { + if isFalse == isTrue { + // Either no or conflicting truthy/falsy value were provided return defaultValue, &invalidFilter{key, args.Get(key)} - } else if isFalse { - return false, nil - } else if isTrue { - return true, nil } - - // This code shouldn't be reached. - return defaultValue, &unreachableCode{Filter: key, Value: args.Get(key)} + return isTrue, nil } // ExactMatch returns true if the source matches exactly one of the values. diff --git a/vendor/github.com/docker/docker/api/types/image/image_inspect.go b/vendor/github.com/docker/docker/api/types/image/image_inspect.go new file mode 100644 index 000000000..78e81f052 --- /dev/null +++ b/vendor/github.com/docker/docker/api/types/image/image_inspect.go @@ -0,0 +1,140 @@ +package image + +import ( + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/storage" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +// RootFS returns Image's RootFS description including the layer IDs. +type RootFS struct { + Type string `json:",omitempty"` + Layers []string `json:",omitempty"` +} + +// InspectResponse contains response of Engine API: +// GET "/images/{name:.*}/json" +type InspectResponse struct { + // ID is the content-addressable ID of an image. + // + // This identifier is a content-addressable digest calculated from the + // image's configuration (which includes the digests of layers used by + // the image). + // + // Note that this digest differs from the `RepoDigests` below, which + // holds digests of image manifests that reference the image. + ID string `json:"Id"` + + // RepoTags is a list of image names/tags in the local image cache that + // reference this image. + // + // Multiple image tags can refer to the same image, and this list may be + // empty if no tags reference the image, in which case the image is + // "untagged", in which case it can still be referenced by its ID. + RepoTags []string + + // RepoDigests is a list of content-addressable digests of locally available + // image manifests that the image is referenced from. Multiple manifests can + // refer to the same image. + // + // These digests are usually only available if the image was either pulled + // from a registry, or if the image was pushed to a registry, which is when + // the manifest is generated and its digest calculated. + RepoDigests []string + + // Parent is the ID of the parent image. + // + // Depending on how the image was created, this field may be empty and + // is only set for images that were built/created locally. This field + // is empty if the image was pulled from an image registry. + Parent string + + // Comment is an optional message that can be set when committing or + // importing the image. + Comment string + + // Created is the date and time at which the image was created, formatted in + // RFC 3339 nano-seconds (time.RFC3339Nano). + // + // This information is only available if present in the image, + // and omitted otherwise. + Created string `json:",omitempty"` + + // Container is the ID of the container that was used to create the image. + // + // Depending on how the image was created, this field may be empty. + // + // Deprecated: this field is omitted in API v1.45, but kept for backward compatibility. + Container string `json:",omitempty"` + + // ContainerConfig is an optional field containing the configuration of the + // container that was last committed when creating the image. + // + // Previous versions of Docker builder used this field to store build cache, + // and it is not in active use anymore. + // + // Deprecated: this field is omitted in API v1.45, but kept for backward compatibility. + ContainerConfig *container.Config `json:",omitempty"` + + // DockerVersion is the version of Docker that was used to build the image. + // + // Depending on how the image was created, this field may be empty. + DockerVersion string + + // Author is the name of the author that was specified when committing the + // image, or as specified through MAINTAINER (deprecated) in the Dockerfile. + Author string + Config *container.Config + + // Architecture is the hardware CPU architecture that the image runs on. + Architecture string + + // Variant is the CPU architecture variant (presently ARM-only). + Variant string `json:",omitempty"` + + // OS is the Operating System the image is built to run on. + Os string + + // OsVersion is the version of the Operating System the image is built to + // run on (especially for Windows). + OsVersion string `json:",omitempty"` + + // Size is the total size of the image including all layers it is composed of. + Size int64 + + // VirtualSize is the total size of the image including all layers it is + // composed of. + // + // Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead. + VirtualSize int64 `json:"VirtualSize,omitempty"` + + // GraphDriver holds information about the storage driver used to store the + // container's and image's filesystem. + GraphDriver storage.DriverData + + // RootFS contains information about the image's RootFS, including the + // layer IDs. + RootFS RootFS + + // Metadata of the image in the local cache. + // + // This information is local to the daemon, and not part of the image itself. + Metadata Metadata + + // Descriptor is the OCI descriptor of the image target. + // It's only set if the daemon provides a multi-platform image store. + // + // WARNING: This is experimental and may change at any time without any backward + // compatibility. + Descriptor *ocispec.Descriptor `json:"Descriptor,omitempty"` + + // Manifests is a list of image manifests available in this image. It + // provides a more detailed view of the platform-specific image manifests or + // other image-attached data like build attestations. + // + // Only available if the daemon provides a multi-platform image store. + // + // WARNING: This is experimental and may change at any time without any backward + // compatibility. + Manifests []ManifestSummary `json:"Manifests,omitempty"` +} diff --git a/vendor/github.com/docker/docker/api/types/image/manifest.go b/vendor/github.com/docker/docker/api/types/image/manifest.go new file mode 100644 index 000000000..db8a00830 --- /dev/null +++ b/vendor/github.com/docker/docker/api/types/image/manifest.go @@ -0,0 +1,99 @@ +package image + +import ( + "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +type ManifestKind string + +const ( + ManifestKindImage ManifestKind = "image" + ManifestKindAttestation ManifestKind = "attestation" + ManifestKindUnknown ManifestKind = "unknown" +) + +type ManifestSummary struct { + // ID is the content-addressable ID of an image and is the same as the + // digest of the image manifest. + // + // Required: true + ID string `json:"ID"` + + // Descriptor is the OCI descriptor of the image. + // + // Required: true + Descriptor ocispec.Descriptor `json:"Descriptor"` + + // Indicates whether all the child content (image config, layers) is + // fully available locally + // + // Required: true + Available bool `json:"Available"` + + // Size is the size information of the content related to this manifest. + // Note: These sizes only take the locally available content into account. + // + // Required: true + Size struct { + // Content is the size (in bytes) of all the locally present + // content in the content store (e.g. image config, layers) + // referenced by this manifest and its children. + // This only includes blobs in the content store. + Content int64 `json:"Content"` + + // Total is the total size (in bytes) of all the locally present + // data (both distributable and non-distributable) that's related to + // this manifest and its children. + // This equal to the sum of [Content] size AND all the sizes in the + // [Size] struct present in the Kind-specific data struct. + // For example, for an image kind (Kind == ManifestKindImage), + // this would include the size of the image content and unpacked + // image snapshots ([Size.Content] + [ImageData.Size.Unpacked]). + Total int64 `json:"Total"` + } `json:"Size"` + + // Kind is the kind of the image manifest. + // + // Required: true + Kind ManifestKind `json:"Kind"` + + // Fields below are specific to the kind of the image manifest. + + // Present only if Kind == ManifestKindImage. + ImageData *ImageProperties `json:"ImageData,omitempty"` + + // Present only if Kind == ManifestKindAttestation. + AttestationData *AttestationProperties `json:"AttestationData,omitempty"` +} + +type ImageProperties struct { + // Platform is the OCI platform object describing the platform of the image. + // + // Required: true + Platform ocispec.Platform `json:"Platform"` + + Size struct { + // Unpacked is the size (in bytes) of the locally unpacked + // (uncompressed) image content that's directly usable by the containers + // running this image. + // It's independent of the distributable content - e.g. + // the image might still have an unpacked data that's still used by + // some container even when the distributable/compressed content is + // already gone. + // + // Required: true + Unpacked int64 `json:"Unpacked"` + } + + // Containers is an array containing the IDs of the containers that are + // using this image. + // + // Required: true + Containers []string `json:"Containers"` +} + +type AttestationProperties struct { + // For is the digest of the image manifest that this attestation is for. + For digest.Digest `json:"For"` +} diff --git a/vendor/github.com/docker/docker/api/types/image/opts.go b/vendor/github.com/docker/docker/api/types/image/opts.go index 8e32c9af8..919510fe3 100644 --- a/vendor/github.com/docker/docker/api/types/image/opts.go +++ b/vendor/github.com/docker/docker/api/types/image/opts.go @@ -38,7 +38,7 @@ type PullOptions struct { // authentication header value in base64 encoded format, or an error if the // privilege request fails. // - // Also see [github.com/docker/docker/api/types.RequestPrivilegeFunc]. + // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. PrivilegeFunc func(context.Context) (string, error) Platform string } @@ -53,7 +53,7 @@ type PushOptions struct { // authentication header value in base64 encoded format, or an error if the // privilege request fails. // - // Also see [github.com/docker/docker/api/types.RequestPrivilegeFunc]. + // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. PrivilegeFunc func(context.Context) (string, error) // Platform is an optional field that selects a specific platform to push @@ -76,6 +76,9 @@ type ListOptions struct { // ContainerCount indicates whether container count should be computed. ContainerCount bool + + // Manifests indicates whether the image manifests should be returned. + Manifests bool } // RemoveOptions holds parameters to remove images. @@ -83,3 +86,31 @@ type RemoveOptions struct { Force bool PruneChildren bool } + +// HistoryOptions holds parameters to get image history. +type HistoryOptions struct { + // Platform from the manifest list to use for history. + Platform *ocispec.Platform +} + +// LoadOptions holds parameters to load images. +type LoadOptions struct { + // Quiet suppresses progress output + Quiet bool + + // Platforms selects the platforms to load if the image is a + // multi-platform image and has multiple variants. + Platforms []ocispec.Platform +} + +type InspectOptions struct { + // Manifests returns the image manifests. + Manifests bool +} + +// SaveOptions holds parameters to save images. +type SaveOptions struct { + // Platforms selects the platforms to save if the image is a + // multi-platform image and has multiple variants. + Platforms []ocispec.Platform +} diff --git a/vendor/github.com/docker/docker/api/types/image/summary.go b/vendor/github.com/docker/docker/api/types/image/summary.go index f1e3e2ef0..c5ae6ab9c 100644 --- a/vendor/github.com/docker/docker/api/types/image/summary.go +++ b/vendor/github.com/docker/docker/api/types/image/summary.go @@ -1,10 +1,7 @@ package image -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command +import ocispec "github.com/opencontainers/image-spec/specs-go/v1" -// Summary summary -// swagger:model Summary type Summary struct { // Number of containers using this image. Includes both stopped and running @@ -17,7 +14,7 @@ type Summary struct { Containers int64 `json:"Containers"` // Date and time at which the image was created as a Unix timestamp - // (number of seconds sinds EPOCH). + // (number of seconds since EPOCH). // // Required: true Created int64 `json:"Created"` @@ -47,6 +44,21 @@ type Summary struct { // Required: true ParentID string `json:"ParentId"` + // Descriptor is the OCI descriptor of the image target. + // It's only set if the daemon provides a multi-platform image store. + // + // WARNING: This is experimental and may change at any time without any backward + // compatibility. + Descriptor *ocispec.Descriptor `json:"Descriptor,omitempty"` + + // Manifests is a list of image manifests available in this image. It + // provides a more detailed view of the platform-specific image manifests or + // other image-attached data like build attestations. + // + // WARNING: This is experimental and may change at any time without any backward + // compatibility. + Manifests []ManifestSummary `json:"Manifests,omitempty"` + // List of content-addressable digests of locally available image manifests // that the image is referenced from. Multiple manifests can refer to the // same image. diff --git a/vendor/github.com/docker/docker/api/types/mount/mount.go b/vendor/github.com/docker/docker/api/types/mount/mount.go index c68dcf65b..d98dbec99 100644 --- a/vendor/github.com/docker/docker/api/types/mount/mount.go +++ b/vendor/github.com/docker/docker/api/types/mount/mount.go @@ -19,6 +19,8 @@ const ( TypeNamedPipe Type = "npipe" // TypeCluster is the type for Swarm Cluster Volumes. TypeCluster Type = "cluster" + // TypeImage is the type for mounting another image's filesystem + TypeImage Type = "image" ) // Mount represents a mount (volume). @@ -34,6 +36,7 @@ type Mount struct { BindOptions *BindOptions `json:",omitempty"` VolumeOptions *VolumeOptions `json:",omitempty"` + ImageOptions *ImageOptions `json:",omitempty"` TmpfsOptions *TmpfsOptions `json:",omitempty"` ClusterOptions *ClusterOptions `json:",omitempty"` } @@ -100,6 +103,10 @@ type VolumeOptions struct { DriverConfig *Driver `json:",omitempty"` } +type ImageOptions struct { + Subpath string `json:",omitempty"` +} + // Driver represents a volume driver. type Driver struct { Name string `json:",omitempty"` diff --git a/vendor/github.com/docker/docker/api/types/network/endpoint.go b/vendor/github.com/docker/docker/api/types/network/endpoint.go index 0fbb40b35..167ac70ab 100644 --- a/vendor/github.com/docker/docker/api/types/network/endpoint.go +++ b/vendor/github.com/docker/docker/api/types/network/endpoint.go @@ -19,6 +19,12 @@ type EndpointSettings struct { // generated address). MacAddress string DriverOpts map[string]string + + // GwPriority determines which endpoint will provide the default gateway + // for the container. The endpoint with the highest priority will be used. + // If multiple endpoints have the same priority, they are lexicographically + // sorted based on their network name, and the one that sorts first is picked. + GwPriority int // Operational data NetworkID string EndpointID string diff --git a/vendor/github.com/docker/docker/api/types/network/network.go b/vendor/github.com/docker/docker/api/types/network/network.go index c8db97a7e..d34b8ab72 100644 --- a/vendor/github.com/docker/docker/api/types/network/network.go +++ b/vendor/github.com/docker/docker/api/types/network/network.go @@ -33,6 +33,7 @@ type CreateRequest struct { type CreateOptions struct { Driver string // Driver is the driver-name used to create the network (e.g. `bridge`, `overlay`) Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level). + EnableIPv4 *bool `json:",omitempty"` // EnableIPv4 represents whether to enable IPv4. EnableIPv6 *bool `json:",omitempty"` // EnableIPv6 represents whether to enable IPv6. IPAM *IPAM // IPAM is the network's IP Address Management. Internal bool // Internal represents if the network is used internal only. @@ -76,7 +77,8 @@ type Inspect struct { Created time.Time // Created is the time the network created Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level) Driver string // Driver is the Driver name used to create the network (e.g. `bridge`, `overlay`) - EnableIPv6 bool // EnableIPv6 represents whether to enable IPv6 + EnableIPv4 bool // EnableIPv4 represents whether IPv4 is enabled + EnableIPv6 bool // EnableIPv6 represents whether IPv6 is enabled IPAM IPAM // IPAM is the network's IP Address Management Internal bool // Internal represents if the network is used internal only Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode. diff --git a/vendor/github.com/docker/docker/api/types/registry/authconfig.go b/vendor/github.com/docker/docker/api/types/registry/authconfig.go index 97a924e37..ebd5e4b9e 100644 --- a/vendor/github.com/docker/docker/api/types/registry/authconfig.go +++ b/vendor/github.com/docker/docker/api/types/registry/authconfig.go @@ -1,17 +1,29 @@ package registry // import "github.com/docker/docker/api/types/registry" import ( + "context" "encoding/base64" "encoding/json" + "fmt" "io" "strings" - - "github.com/pkg/errors" ) // AuthHeader is the name of the header used to send encoded registry // authorization credentials for registry operations (push/pull). const AuthHeader = "X-Registry-Auth" +// RequestAuthConfig is a function interface that clients can supply +// to retry operations after getting an authorization error. +// +// The function must return the [AuthHeader] value ([AuthConfig]), encoded +// in base64url format ([RFC4648, section 5]), which can be decoded by +// [DecodeAuthConfig]. +// +// It must return an error if the privilege request fails. +// +// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5 +type RequestAuthConfig func(context.Context) (string, error) + // AuthConfig contains authorization information for connecting to a Registry. type AuthConfig struct { Username string `json:"username,omitempty"` @@ -34,10 +46,9 @@ type AuthConfig struct { } // EncodeAuthConfig serializes the auth configuration as a base64url encoded -// RFC4648, section 5) JSON string for sending through the X-Registry-Auth header. +// ([RFC4648, section 5]) JSON string for sending through the X-Registry-Auth header. // -// For details on base64url encoding, see: -// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5 +// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5 func EncodeAuthConfig(authConfig AuthConfig) (string, error) { buf, err := json.Marshal(authConfig) if err != nil { @@ -46,15 +57,14 @@ func EncodeAuthConfig(authConfig AuthConfig) (string, error) { return base64.URLEncoding.EncodeToString(buf), nil } -// DecodeAuthConfig decodes base64url encoded (RFC4648, section 5) JSON +// DecodeAuthConfig decodes base64url encoded ([RFC4648, section 5]) JSON // authentication information as sent through the X-Registry-Auth header. // -// This function always returns an AuthConfig, even if an error occurs. It is up +// This function always returns an [AuthConfig], even if an error occurs. It is up // to the caller to decide if authentication is required, and if the error can // be ignored. // -// For details on base64url encoding, see: -// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5 +// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5 func DecodeAuthConfig(authEncoded string) (*AuthConfig, error) { if authEncoded == "" { return &AuthConfig{}, nil @@ -69,7 +79,7 @@ func DecodeAuthConfig(authEncoded string) (*AuthConfig, error) { // clients and API versions. Current clients and API versions expect authentication // to be provided through the X-Registry-Auth header. // -// Like DecodeAuthConfig, this function always returns an AuthConfig, even if an +// Like [DecodeAuthConfig], this function always returns an [AuthConfig], even if an // error occurs. It is up to the caller to decide if authentication is required, // and if the error can be ignored. func DecodeAuthConfigBody(rdr io.ReadCloser) (*AuthConfig, error) { @@ -87,7 +97,7 @@ func decodeAuthConfigFromReader(rdr io.Reader) (*AuthConfig, error) { } func invalid(err error) error { - return errInvalidParameter{errors.Wrap(err, "invalid X-Registry-Auth header")} + return errInvalidParameter{fmt.Errorf("invalid X-Registry-Auth header: %w", err)} } type errInvalidParameter struct{ error } diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go index 75ee07b15..b0a4d604f 100644 --- a/vendor/github.com/docker/docker/api/types/registry/registry.go +++ b/vendor/github.com/docker/docker/api/types/registry/registry.go @@ -9,11 +9,29 @@ import ( // ServiceConfig stores daemon registry services configuration. type ServiceConfig struct { - AllowNondistributableArtifactsCIDRs []*NetIPNet - AllowNondistributableArtifactsHostnames []string - InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"` - IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"` - Mirrors []string + AllowNondistributableArtifactsCIDRs []*NetIPNet `json:"AllowNondistributableArtifactsCIDRs,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. + AllowNondistributableArtifactsHostnames []string `json:"AllowNondistributableArtifactsHostnames,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. + + InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"` + IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"` + Mirrors []string +} + +// MarshalJSON implements a custom marshaler to include legacy fields +// in API responses. +func (sc ServiceConfig) MarshalJSON() ([]byte, error) { + tmp := map[string]interface{}{ + "InsecureRegistryCIDRs": sc.InsecureRegistryCIDRs, + "IndexConfigs": sc.IndexConfigs, + "Mirrors": sc.Mirrors, + } + if sc.AllowNondistributableArtifactsCIDRs != nil { + tmp["AllowNondistributableArtifactsCIDRs"] = nil + } + if sc.AllowNondistributableArtifactsHostnames != nil { + tmp["AllowNondistributableArtifactsHostnames"] = nil + } + return json.Marshal(tmp) } // NetIPNet is the net.IPNet type, which can be marshalled and diff --git a/vendor/github.com/docker/docker/api/types/registry/search.go b/vendor/github.com/docker/docker/api/types/registry/search.go index a0a1eec54..994ca4c6f 100644 --- a/vendor/github.com/docker/docker/api/types/registry/search.go +++ b/vendor/github.com/docker/docker/api/types/registry/search.go @@ -10,11 +10,12 @@ import ( type SearchOptions struct { RegistryAuth string - // PrivilegeFunc is a [types.RequestPrivilegeFunc] the client can - // supply to retry operations after getting an authorization error. + // PrivilegeFunc is a function that clients can supply to retry operations + // after getting an authorization error. This function returns the registry + // authentication header value in base64 encoded format, or an error if the + // privilege request fails. // - // It must return the registry authentication header value in base64 - // format, or an error if the privilege request fails. + // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. PrivilegeFunc func(context.Context) (string, error) Filters filters.Args Limit int diff --git a/vendor/github.com/docker/docker/api/types/graph_driver_data.go b/vendor/github.com/docker/docker/api/types/storage/driver_data.go similarity index 75% rename from vendor/github.com/docker/docker/api/types/graph_driver_data.go rename to vendor/github.com/docker/docker/api/types/storage/driver_data.go index ce3deb331..009e21309 100644 --- a/vendor/github.com/docker/docker/api/types/graph_driver_data.go +++ b/vendor/github.com/docker/docker/api/types/storage/driver_data.go @@ -1,13 +1,13 @@ -package types +package storage // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command -// GraphDriverData Information about the storage driver used to store the container's and +// DriverData Information about the storage driver used to store the container's and // image's filesystem. // -// swagger:model GraphDriverData -type GraphDriverData struct { +// swagger:model DriverData +type DriverData struct { // Low-level storage metadata, provided as key/value pairs. // diff --git a/vendor/github.com/docker/docker/api/types/swarm/swarm.go b/vendor/github.com/docker/docker/api/types/swarm/swarm.go index 3eae4b9b2..1b4be6fff 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/swarm.go +++ b/vendor/github.com/docker/docker/api/types/swarm/swarm.go @@ -122,7 +122,7 @@ type CAConfig struct { SigningCAKey string `json:",omitempty"` // If this value changes, and there is no specified signing cert and key, - // then the swarm is forced to generate a new root certificate ane key. + // then the swarm is forced to generate a new root certificate and key. ForceRotate uint64 `json:",omitempty"` } diff --git a/vendor/github.com/docker/docker/api/types/system/info.go b/vendor/github.com/docker/docker/api/types/system/info.go index c66a2afb8..8a2444da2 100644 --- a/vendor/github.com/docker/docker/api/types/system/info.go +++ b/vendor/github.com/docker/docker/api/types/system/info.go @@ -29,8 +29,8 @@ type Info struct { CPUSet bool PidsLimit bool IPv4Forwarding bool - BridgeNfIptables bool - BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` + BridgeNfIptables bool `json:"BridgeNfIptables"` // Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release. + BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` // Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release. Debug bool NFd int OomKillDisable bool @@ -137,8 +137,13 @@ type PluginsInfo struct { // Commit holds the Git-commit (SHA1) that a binary was built from, as reported // in the version-string of external tools, such as containerd, or runC. type Commit struct { - ID string // ID is the actual commit ID of external tool. - Expected string // Expected is the commit ID of external tool expected by dockerd as set at build time. + // ID is the actual commit ID or version of external tool. + ID string + + // Expected is the commit ID of external tool expected by dockerd as set at build time. + // + // Deprecated: this field is no longer used in API v1.49, but kept for backward-compatibility with older API versions. + Expected string } // NetworkAddressPool is a temp struct used by [Info] struct. diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go index fe99b7439..82ae339c3 100644 --- a/vendor/github.com/docker/docker/api/types/types.go +++ b/vendor/github.com/docker/docker/api/types/types.go @@ -6,11 +6,8 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/volume" - "github.com/docker/go-connections/nat" ) const ( @@ -21,145 +18,6 @@ const ( MediaTypeMultiplexedStream = "application/vnd.docker.multiplexed-stream" ) -// RootFS returns Image's RootFS description including the layer IDs. -type RootFS struct { - Type string `json:",omitempty"` - Layers []string `json:",omitempty"` -} - -// ImageInspect contains response of Engine API: -// GET "/images/{name:.*}/json" -type ImageInspect struct { - // ID is the content-addressable ID of an image. - // - // This identifier is a content-addressable digest calculated from the - // image's configuration (which includes the digests of layers used by - // the image). - // - // Note that this digest differs from the `RepoDigests` below, which - // holds digests of image manifests that reference the image. - ID string `json:"Id"` - - // RepoTags is a list of image names/tags in the local image cache that - // reference this image. - // - // Multiple image tags can refer to the same image, and this list may be - // empty if no tags reference the image, in which case the image is - // "untagged", in which case it can still be referenced by its ID. - RepoTags []string - - // RepoDigests is a list of content-addressable digests of locally available - // image manifests that the image is referenced from. Multiple manifests can - // refer to the same image. - // - // These digests are usually only available if the image was either pulled - // from a registry, or if the image was pushed to a registry, which is when - // the manifest is generated and its digest calculated. - RepoDigests []string - - // Parent is the ID of the parent image. - // - // Depending on how the image was created, this field may be empty and - // is only set for images that were built/created locally. This field - // is empty if the image was pulled from an image registry. - Parent string - - // Comment is an optional message that can be set when committing or - // importing the image. - Comment string - - // Created is the date and time at which the image was created, formatted in - // RFC 3339 nano-seconds (time.RFC3339Nano). - // - // This information is only available if present in the image, - // and omitted otherwise. - Created string `json:",omitempty"` - - // Container is the ID of the container that was used to create the image. - // - // Depending on how the image was created, this field may be empty. - // - // Deprecated: this field is omitted in API v1.45, but kept for backward compatibility. - Container string `json:",omitempty"` - - // ContainerConfig is an optional field containing the configuration of the - // container that was last committed when creating the image. - // - // Previous versions of Docker builder used this field to store build cache, - // and it is not in active use anymore. - // - // Deprecated: this field is omitted in API v1.45, but kept for backward compatibility. - ContainerConfig *container.Config `json:",omitempty"` - - // DockerVersion is the version of Docker that was used to build the image. - // - // Depending on how the image was created, this field may be empty. - DockerVersion string - - // Author is the name of the author that was specified when committing the - // image, or as specified through MAINTAINER (deprecated) in the Dockerfile. - Author string - Config *container.Config - - // Architecture is the hardware CPU architecture that the image runs on. - Architecture string - - // Variant is the CPU architecture variant (presently ARM-only). - Variant string `json:",omitempty"` - - // OS is the Operating System the image is built to run on. - Os string - - // OsVersion is the version of the Operating System the image is built to - // run on (especially for Windows). - OsVersion string `json:",omitempty"` - - // Size is the total size of the image including all layers it is composed of. - Size int64 - - // VirtualSize is the total size of the image including all layers it is - // composed of. - // - // Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead. - VirtualSize int64 `json:"VirtualSize,omitempty"` - - // GraphDriver holds information about the storage driver used to store the - // container's and image's filesystem. - GraphDriver GraphDriverData - - // RootFS contains information about the image's RootFS, including the - // layer IDs. - RootFS RootFS - - // Metadata of the image in the local cache. - // - // This information is local to the daemon, and not part of the image itself. - Metadata image.Metadata -} - -// Container contains response of Engine API: -// GET "/containers/json" -type Container struct { - ID string `json:"Id"` - Names []string - Image string - ImageID string - Command string - Created int64 - Ports []Port - SizeRw int64 `json:",omitempty"` - SizeRootFs int64 `json:",omitempty"` - Labels map[string]string - State string - Status string - HostConfig struct { - NetworkMode string `json:",omitempty"` - Annotations map[string]string `json:",omitempty"` - } - NetworkSettings *SummaryNetworkSettings - Mounts []MountPoint -} - // Ping contains response of Engine API: // GET "/_ping" type Ping struct { @@ -205,176 +63,6 @@ type Version struct { BuildTime string `json:",omitempty"` } -// HealthcheckResult stores information about a single run of a healthcheck probe -type HealthcheckResult struct { - Start time.Time // Start is the time this check started - End time.Time // End is the time this check ended - ExitCode int // ExitCode meanings: 0=healthy, 1=unhealthy, 2=reserved (considered unhealthy), else=error running probe - Output string // Output from last check -} - -// Health states -const ( - NoHealthcheck = "none" // Indicates there is no healthcheck - Starting = "starting" // Starting indicates that the container is not yet ready - Healthy = "healthy" // Healthy indicates that the container is running correctly - Unhealthy = "unhealthy" // Unhealthy indicates that the container has a problem -) - -// Health stores information about the container's healthcheck results -type Health struct { - Status string // Status is one of Starting, Healthy or Unhealthy - FailingStreak int // FailingStreak is the number of consecutive failures - Log []*HealthcheckResult // Log contains the last few results (oldest first) -} - -// ContainerState stores container's running state -// it's part of ContainerJSONBase and will return by "inspect" command -type ContainerState struct { - Status string // String representation of the container state. Can be one of "created", "running", "paused", "restarting", "removing", "exited", or "dead" - Running bool - Paused bool - Restarting bool - OOMKilled bool - Dead bool - Pid int - ExitCode int - Error string - StartedAt string - FinishedAt string - Health *Health `json:",omitempty"` -} - -// ContainerJSONBase contains response of Engine API: -// GET "/containers/{name:.*}/json" -type ContainerJSONBase struct { - ID string `json:"Id"` - Created string - Path string - Args []string - State *ContainerState - Image string - ResolvConfPath string - HostnamePath string - HostsPath string - LogPath string - Node *ContainerNode `json:",omitempty"` // Deprecated: Node was only propagated by Docker Swarm standalone API. It sill be removed in the next release. - Name string - RestartCount int - Driver string - Platform string - MountLabel string - ProcessLabel string - AppArmorProfile string - ExecIDs []string - HostConfig *container.HostConfig - GraphDriver GraphDriverData - SizeRw *int64 `json:",omitempty"` - SizeRootFs *int64 `json:",omitempty"` -} - -// ContainerJSON is newly used struct along with MountPoint -type ContainerJSON struct { - *ContainerJSONBase - Mounts []MountPoint - Config *container.Config - NetworkSettings *NetworkSettings -} - -// NetworkSettings exposes the network settings in the api -type NetworkSettings struct { - NetworkSettingsBase - DefaultNetworkSettings - Networks map[string]*network.EndpointSettings -} - -// SummaryNetworkSettings provides a summary of container's networks -// in /containers/json -type SummaryNetworkSettings struct { - Networks map[string]*network.EndpointSettings -} - -// NetworkSettingsBase holds networking state for a container when inspecting it. -type NetworkSettingsBase struct { - Bridge string // Bridge contains the name of the default bridge interface iff it was set through the daemon --bridge flag. - SandboxID string // SandboxID uniquely represents a container's network stack - SandboxKey string // SandboxKey identifies the sandbox - Ports nat.PortMap // Ports is a collection of PortBinding indexed by Port - - // HairpinMode specifies if hairpin NAT should be enabled on the virtual interface - // - // Deprecated: This field is never set and will be removed in a future release. - HairpinMode bool - // LinkLocalIPv6Address is an IPv6 unicast address using the link-local prefix - // - // Deprecated: This field is never set and will be removed in a future release. - LinkLocalIPv6Address string - // LinkLocalIPv6PrefixLen is the prefix length of an IPv6 unicast address - // - // Deprecated: This field is never set and will be removed in a future release. - LinkLocalIPv6PrefixLen int - SecondaryIPAddresses []network.Address // Deprecated: This field is never set and will be removed in a future release. - SecondaryIPv6Addresses []network.Address // Deprecated: This field is never set and will be removed in a future release. -} - -// DefaultNetworkSettings holds network information -// during the 2 release deprecation period. -// It will be removed in Docker 1.11. -type DefaultNetworkSettings struct { - EndpointID string // EndpointID uniquely represents a service endpoint in a Sandbox - Gateway string // Gateway holds the gateway address for the network - GlobalIPv6Address string // GlobalIPv6Address holds network's global IPv6 address - GlobalIPv6PrefixLen int // GlobalIPv6PrefixLen represents mask length of network's global IPv6 address - IPAddress string // IPAddress holds the IPv4 address for the network - IPPrefixLen int // IPPrefixLen represents mask length of network's IPv4 address - IPv6Gateway string // IPv6Gateway holds gateway address specific for IPv6 - MacAddress string // MacAddress holds the MAC address for the network -} - -// MountPoint represents a mount point configuration inside the container. -// This is used for reporting the mountpoints in use by a container. -type MountPoint struct { - // Type is the type of mount, see `Type` definitions in - // github.com/docker/docker/api/types/mount.Type - Type mount.Type `json:",omitempty"` - - // Name is the name reference to the underlying data defined by `Source` - // e.g., the volume name. - Name string `json:",omitempty"` - - // Source is the source location of the mount. - // - // For volumes, this contains the storage location of the volume (within - // `/var/lib/docker/volumes/`). For bind-mounts, and `npipe`, this contains - // the source (host) part of the bind-mount. For `tmpfs` mount points, this - // field is empty. - Source string - - // Destination is the path relative to the container root (`/`) where the - // Source is mounted inside the container. - Destination string - - // Driver is the volume driver used to create the volume (if it is a volume). - Driver string `json:",omitempty"` - - // Mode is a comma separated list of options supplied by the user when - // creating the bind/volume mount. - // - // The default is platform-specific (`"z"` on Linux, empty on Windows). - Mode string - - // RW indicates whether the mount is mounted writable (read-write). - RW bool - - // Propagation describes how mounts are propagated from the host into the - // mount point, and vice-versa. Refer to the Linux kernel documentation - // for details: - // https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt - // - // This field is not used on Windows. - Propagation mount.Propagation -} - // DiskUsageObject represents an object type used for disk usage query filtering. type DiskUsageObject string @@ -401,7 +89,7 @@ type DiskUsageOptions struct { type DiskUsage struct { LayersSize int64 Images []*image.Summary - Containers []*Container + Containers []*container.Summary Volumes []*volume.Volume BuildCache []*BuildCache BuilderSize int64 `json:",omitempty"` // Deprecated: deprecated in API 1.38, and no longer used since API 1.40. @@ -481,7 +169,11 @@ type BuildCache struct { // BuildCachePruneOptions hold parameters to prune the build cache type BuildCachePruneOptions struct { - All bool - KeepStorage int64 - Filters filters.Args + All bool + ReservedSpace int64 + MaxUsedSpace int64 + MinFreeSpace int64 + Filters filters.Args + + KeepStorage int64 // Deprecated: deprecated in API 1.48. } diff --git a/vendor/github.com/docker/docker/api/types/types_deprecated.go b/vendor/github.com/docker/docker/api/types/types_deprecated.go index 43ffe104a..93e4336ad 100644 --- a/vendor/github.com/docker/docker/api/types/types_deprecated.go +++ b/vendor/github.com/docker/docker/api/types/types_deprecated.go @@ -1,210 +1,115 @@ package types import ( + "context" + + "github.com/docker/docker/api/types/common" "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/api/types/volume" + "github.com/docker/docker/api/types/storage" ) -// ImagesPruneReport contains the response for Engine API: -// POST "/images/prune" -// -// Deprecated: use [image.PruneReport]. -type ImagesPruneReport = image.PruneReport - -// VolumesPruneReport contains the response for Engine API: -// POST "/volumes/prune". -// -// Deprecated: use [volume.PruneReport]. -type VolumesPruneReport = volume.PruneReport - -// NetworkCreateRequest is the request message sent to the server for network create call. -// -// Deprecated: use [network.CreateRequest]. -type NetworkCreateRequest = network.CreateRequest - -// NetworkCreate is the expected body of the "create network" http request message -// -// Deprecated: use [network.CreateOptions]. -type NetworkCreate = network.CreateOptions - -// NetworkListOptions holds parameters to filter the list of networks with. -// -// Deprecated: use [network.ListOptions]. -type NetworkListOptions = network.ListOptions - -// NetworkCreateResponse is the response message sent by the server for network create call. -// -// Deprecated: use [network.CreateResponse]. -type NetworkCreateResponse = network.CreateResponse - -// NetworkInspectOptions holds parameters to inspect network. -// -// Deprecated: use [network.InspectOptions]. -type NetworkInspectOptions = network.InspectOptions - -// NetworkConnect represents the data to be used to connect a container to the network -// -// Deprecated: use [network.ConnectOptions]. -type NetworkConnect = network.ConnectOptions - -// NetworkDisconnect represents the data to be used to disconnect a container from the network -// -// Deprecated: use [network.DisconnectOptions]. -type NetworkDisconnect = network.DisconnectOptions - -// EndpointResource contains network resources allocated and used for a container in a network. +// IDResponse Response to an API call that returns just an Id. // -// Deprecated: use [network.EndpointResource]. -type EndpointResource = network.EndpointResource +// Deprecated: use either [container.CommitResponse] or [container.ExecCreateResponse]. It will be removed in the next release. +type IDResponse = common.IDResponse -// NetworkResource is the body of the "get network" http response message/ +// ContainerJSONBase contains response of Engine API GET "/containers/{name:.*}/json" +// for API version 1.18 and older. // -// Deprecated: use [network.Inspect] or [network.Summary] (for list operations). -type NetworkResource = network.Inspect +// Deprecated: use [container.InspectResponse] or [container.ContainerJSONBase]. It will be removed in the next release. +type ContainerJSONBase = container.ContainerJSONBase -// NetworksPruneReport contains the response for Engine API: -// POST "/networks/prune" +// ContainerJSON is the response for the GET "/containers/{name:.*}/json" +// endpoint. // -// Deprecated: use [network.PruneReport]. -type NetworksPruneReport = network.PruneReport +// Deprecated: use [container.InspectResponse]. It will be removed in the next release. +type ContainerJSON = container.InspectResponse -// ExecConfig is a small subset of the Config struct that holds the configuration -// for the exec feature of docker. +// Container contains response of Engine API: +// GET "/containers/json" // -// Deprecated: use [container.ExecOptions]. -type ExecConfig = container.ExecOptions +// Deprecated: use [container.Summary]. +type Container = container.Summary -// ExecStartCheck is a temp struct used by execStart -// Config fields is part of ExecConfig in runconfig package +// ContainerState stores container's running state // -// Deprecated: use [container.ExecStartOptions] or [container.ExecAttachOptions]. -type ExecStartCheck = container.ExecStartOptions +// Deprecated: use [container.State]. +type ContainerState = container.State -// ContainerExecInspect holds information returned by exec inspect. +// NetworkSettings exposes the network settings in the api. // -// Deprecated: use [container.ExecInspect]. -type ContainerExecInspect = container.ExecInspect +// Deprecated: use [container.NetworkSettings]. +type NetworkSettings = container.NetworkSettings -// ContainersPruneReport contains the response for Engine API: -// POST "/containers/prune" +// NetworkSettingsBase holds networking state for a container when inspecting it. // -// Deprecated: use [container.PruneReport]. -type ContainersPruneReport = container.PruneReport +// Deprecated: use [container.NetworkSettingsBase]. +type NetworkSettingsBase = container.NetworkSettingsBase -// ContainerPathStat is used to encode the header from -// GET "/containers/{name:.*}/archive" -// "Name" is the file or directory name. +// DefaultNetworkSettings holds network information +// during the 2 release deprecation period. +// It will be removed in Docker 1.11. // -// Deprecated: use [container.PathStat]. -type ContainerPathStat = container.PathStat +// Deprecated: use [container.DefaultNetworkSettings]. +type DefaultNetworkSettings = container.DefaultNetworkSettings -// CopyToContainerOptions holds information -// about files to copy into a container. +// SummaryNetworkSettings provides a summary of container's networks +// in /containers/json. // -// Deprecated: use [container.CopyToContainerOptions], -type CopyToContainerOptions = container.CopyToContainerOptions +// Deprecated: use [container.NetworkSettingsSummary]. +type SummaryNetworkSettings = container.NetworkSettingsSummary -// ContainerStats contains response of Engine API: -// GET "/stats" -// -// Deprecated: use [container.StatsResponseReader]. -type ContainerStats = container.StatsResponseReader - -// ThrottlingData stores CPU throttling stats of one running container. -// Not used on Windows. -// -// Deprecated: use [container.ThrottlingData]. -type ThrottlingData = container.ThrottlingData - -// CPUUsage stores All CPU stats aggregated since container inception. -// -// Deprecated: use [container.CPUUsage]. -type CPUUsage = container.CPUUsage - -// CPUStats aggregates and wraps all CPU related info of container -// -// Deprecated: use [container.CPUStats]. -type CPUStats = container.CPUStats - -// MemoryStats aggregates all memory stats since container inception on Linux. -// Windows returns stats for commit and private working set only. -// -// Deprecated: use [container.MemoryStats]. -type MemoryStats = container.MemoryStats - -// BlkioStatEntry is one small entity to store a piece of Blkio stats -// Not used on Windows. -// -// Deprecated: use [container.BlkioStatEntry]. -type BlkioStatEntry = container.BlkioStatEntry - -// BlkioStats stores All IO service stats for data read and write. -// This is a Linux specific structure as the differences between expressing -// block I/O on Windows and Linux are sufficiently significant to make -// little sense attempting to morph into a combined structure. -// -// Deprecated: use [container.BlkioStats]. -type BlkioStats = container.BlkioStats - -// StorageStats is the disk I/O stats for read/write on Windows. -// -// Deprecated: use [container.StorageStats]. -type StorageStats = container.StorageStats - -// NetworkStats aggregates the network stats of one container -// -// Deprecated: use [container.NetworkStats]. -type NetworkStats = container.NetworkStats +// Health states +const ( + NoHealthcheck = container.NoHealthcheck // Deprecated: use [container.NoHealthcheck]. + Starting = container.Starting // Deprecated: use [container.Starting]. + Healthy = container.Healthy // Deprecated: use [container.Healthy]. + Unhealthy = container.Unhealthy // Deprecated: use [container.Unhealthy]. +) -// PidsStats contains the stats of a container's pids +// Health stores information about the container's healthcheck results. // -// Deprecated: use [container.PidsStats]. -type PidsStats = container.PidsStats +// Deprecated: use [container.Health]. +type Health = container.Health -// Stats is Ultimate struct aggregating all types of stats of one container +// HealthcheckResult stores information about a single run of a healthcheck probe. // -// Deprecated: use [container.Stats]. -type Stats = container.Stats +// Deprecated: use [container.HealthcheckResult]. +type HealthcheckResult = container.HealthcheckResult -// StatsJSON is newly used Networks +// MountPoint represents a mount point configuration inside the container. +// This is used for reporting the mountpoints in use by a container. // -// Deprecated: use [container.StatsResponse]. -type StatsJSON = container.StatsResponse +// Deprecated: use [container.MountPoint]. +type MountPoint = container.MountPoint -// EventsOptions holds parameters to filter events with. +// Port An open port on a container // -// Deprecated: use [events.ListOptions]. -type EventsOptions = events.ListOptions +// Deprecated: use [container.Port]. +type Port = container.Port -// ImageSearchOptions holds parameters to search images with. +// GraphDriverData Information about the storage driver used to store the container's and +// image's filesystem. // -// Deprecated: use [registry.SearchOptions]. -type ImageSearchOptions = registry.SearchOptions +// Deprecated: use [storage.DriverData]. +type GraphDriverData = storage.DriverData -// ImageImportSource holds source information for ImageImport +// RootFS returns Image's RootFS description including the layer IDs. // -// Deprecated: use [image.ImportSource]. -type ImageImportSource image.ImportSource +// Deprecated: use [image.RootFS]. +type RootFS = image.RootFS -// ImageLoadResponse returns information to the client about a load process. +// ImageInspect contains response of Engine API: +// GET "/images/{name:.*}/json" // -// Deprecated: use [image.LoadResponse]. -type ImageLoadResponse = image.LoadResponse +// Deprecated: use [image.InspectResponse]. +type ImageInspect = image.InspectResponse -// ContainerNode stores information about the node that a container -// is running on. It's only used by the Docker Swarm standalone API. +// RequestPrivilegeFunc is a function interface that clients can supply to +// retry operations after getting an authorization error. +// This function returns the registry authentication header value in base64 +// format, or an error if the privilege request fails. // -// Deprecated: ContainerNode was used for the classic Docker Swarm standalone API. It will be removed in the next release. -type ContainerNode struct { - ID string - IPAddress string `json:"IP"` - Addr string - Name string - Cpus int - Memory int64 - Labels map[string]string -} +// Deprecated: moved to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. +type RequestPrivilegeFunc func(context.Context) (string, error) diff --git a/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go b/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go index bbd9ff0b8..618a48162 100644 --- a/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go +++ b/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go @@ -414,7 +414,7 @@ type Info struct { // the Volume has not been successfully created yet. VolumeID string `json:",omitempty"` - // AccessibleTopolgoy is the topology this volume is actually accessible + // AccessibleTopology is the topology this volume is actually accessible // from. AccessibleTopology []Topology `json:",omitempty"` } diff --git a/vendor/github.com/docker/docker/client/build_cancel.go b/vendor/github.com/docker/docker/client/build_cancel.go index b76bf366b..51a73cdb2 100644 --- a/vendor/github.com/docker/docker/client/build_cancel.go +++ b/vendor/github.com/docker/docker/client/build_cancel.go @@ -10,7 +10,7 @@ func (cli *Client) BuildCancel(ctx context.Context, id string) error { query := url.Values{} query.Set("id", id) - serverResp, err := cli.post(ctx, "/build/cancel", query, nil, nil) - ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/build/cancel", query, nil, nil) + ensureReaderClosed(resp) return err } diff --git a/vendor/github.com/docker/docker/client/build_prune.go b/vendor/github.com/docker/docker/client/build_prune.go index 1a830f413..92b47d183 100644 --- a/vendor/github.com/docker/docker/client/build_prune.go +++ b/vendor/github.com/docker/docker/client/build_prune.go @@ -17,27 +17,38 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePru return nil, err } - report := types.BuildCachePruneReport{} - query := url.Values{} if opts.All { query.Set("all", "1") } - query.Set("keep-storage", strconv.Itoa(int(opts.KeepStorage))) + + if opts.KeepStorage != 0 { + query.Set("keep-storage", strconv.Itoa(int(opts.KeepStorage))) + } + if opts.ReservedSpace != 0 { + query.Set("reserved-space", strconv.Itoa(int(opts.ReservedSpace))) + } + if opts.MaxUsedSpace != 0 { + query.Set("max-used-space", strconv.Itoa(int(opts.MaxUsedSpace))) + } + if opts.MinFreeSpace != 0 { + query.Set("min-free-space", strconv.Itoa(int(opts.MinFreeSpace))) + } f, err := filters.ToJSON(opts.Filters) if err != nil { return nil, errors.Wrap(err, "prune could not marshal filters option") } query.Set("filters", f) - serverResp, err := cli.post(ctx, "/build/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/build/prune", query, nil, nil) + defer ensureReaderClosed(resp) if err != nil { return nil, err } - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { + report := types.BuildCachePruneReport{} + if err := json.NewDecoder(resp.Body).Decode(&report); err != nil { return nil, errors.Wrap(err, "error retrieving disk usage") } diff --git a/vendor/github.com/docker/docker/client/interface_experimental.go b/vendor/github.com/docker/docker/client/checkpoint.go similarity index 76% rename from vendor/github.com/docker/docker/client/interface_experimental.go rename to vendor/github.com/docker/docker/client/checkpoint.go index c585c1045..f690f7c95 100644 --- a/vendor/github.com/docker/docker/client/interface_experimental.go +++ b/vendor/github.com/docker/docker/client/checkpoint.go @@ -6,11 +6,11 @@ import ( "github.com/docker/docker/api/types/checkpoint" ) -type apiClientExperimental interface { - CheckpointAPIClient -} - -// CheckpointAPIClient defines API client methods for the checkpoints +// CheckpointAPIClient defines API client methods for the checkpoints. +// +// Experimental: checkpoint and restore is still an experimental feature, +// and only available if the daemon is running with experimental features +// enabled. type CheckpointAPIClient interface { CheckpointCreate(ctx context.Context, container string, options checkpoint.CreateOptions) error CheckpointDelete(ctx context.Context, container string, options checkpoint.DeleteOptions) error diff --git a/vendor/github.com/docker/docker/client/checkpoint_create.go b/vendor/github.com/docker/docker/client/checkpoint_create.go index 9746d288d..7b06fee31 100644 --- a/vendor/github.com/docker/docker/client/checkpoint_create.go +++ b/vendor/github.com/docker/docker/client/checkpoint_create.go @@ -7,8 +7,13 @@ import ( ) // CheckpointCreate creates a checkpoint from the given container with the given name -func (cli *Client) CheckpointCreate(ctx context.Context, container string, options checkpoint.CreateOptions) error { - resp, err := cli.post(ctx, "/containers/"+container+"/checkpoints", nil, options, nil) +func (cli *Client) CheckpointCreate(ctx context.Context, containerID string, options checkpoint.CreateOptions) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + + resp, err := cli.post(ctx, "/containers/"+containerID+"/checkpoints", nil, options, nil) ensureReaderClosed(resp) return err } diff --git a/vendor/github.com/docker/docker/client/checkpoint_delete.go b/vendor/github.com/docker/docker/client/checkpoint_delete.go index b968c2b23..d15162ea0 100644 --- a/vendor/github.com/docker/docker/client/checkpoint_delete.go +++ b/vendor/github.com/docker/docker/client/checkpoint_delete.go @@ -9,6 +9,11 @@ import ( // CheckpointDelete deletes the checkpoint with the given name from the given container func (cli *Client) CheckpointDelete(ctx context.Context, containerID string, options checkpoint.DeleteOptions) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + query := url.Values{} if options.CheckpointDir != "" { query.Set("dir", options.CheckpointDir) diff --git a/vendor/github.com/docker/docker/client/checkpoint_list.go b/vendor/github.com/docker/docker/client/checkpoint_list.go index 8feb1f3f7..9e7963f0b 100644 --- a/vendor/github.com/docker/docker/client/checkpoint_list.go +++ b/vendor/github.com/docker/docker/client/checkpoint_list.go @@ -23,6 +23,6 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options return checkpoints, err } - err = json.NewDecoder(resp.body).Decode(&checkpoints) + err = json.NewDecoder(resp.Body).Decode(&checkpoints) return checkpoints, err } diff --git a/vendor/github.com/docker/docker/client/client.go b/vendor/github.com/docker/docker/client/client.go index 60d91bc65..cd47f05eb 100644 --- a/vendor/github.com/docker/docker/client/client.go +++ b/vendor/github.com/docker/docker/client/client.go @@ -2,7 +2,7 @@ Package client is a Go client for the Docker Engine API. For more information about the Engine API, see the documentation: -https://docs.docker.com/engine/api/ +https://docs.docker.com/reference/api/engine/ # Usage @@ -59,7 +59,6 @@ import ( "github.com/docker/go-connections/sockets" "github.com/pkg/errors" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" - "go.opentelemetry.io/otel/trace" ) // DummyHost is a hostname used for local communication. @@ -99,6 +98,9 @@ const DummyHost = "api.moby.localhost" // recent version before negotiation was introduced. const fallbackAPIVersion = "1.24" +// Ensure that Client always implements APIClient. +var _ APIClient = &Client{} + // Client is the API client that performs all operations // against a docker server. type Client struct { @@ -138,7 +140,7 @@ type Client struct { // negotiateLock is used to single-flight the version negotiation process negotiateLock sync.Mutex - tp trace.TracerProvider + traceOpts []otelhttp.Option // When the client transport is an *http.Transport (default) we need to do some extra things (like closing idle connections). // Store the original transport as the http.Client transport will be wrapped with tracing libs. @@ -200,6 +202,12 @@ func NewClientWithOpts(ops ...Opt) (*Client, error) { client: client, proto: hostURL.Scheme, addr: hostURL.Host, + + traceOpts: []otelhttp.Option{ + otelhttp.WithSpanNameFormatter(func(_ string, req *http.Request) string { + return req.Method + " " + req.URL.Path + }), + }, } for _, op := range ops { @@ -227,13 +235,7 @@ func NewClientWithOpts(ops ...Opt) (*Client, error) { } } - c.client.Transport = otelhttp.NewTransport( - c.client.Transport, - otelhttp.WithTracerProvider(c.tp), - otelhttp.WithSpanNameFormatter(func(_ string, req *http.Request) string { - return req.Method + " " + req.URL.Path - }), - ) + c.client.Transport = otelhttp.NewTransport(c.client.Transport, c.traceOpts...) return c, nil } @@ -247,6 +249,14 @@ func (cli *Client) tlsConfig() *tls.Config { func defaultHTTPClient(hostURL *url.URL) (*http.Client, error) { transport := &http.Transport{} + // Necessary to prevent long-lived processes using the + // client from leaking connections due to idle connections + // not being released. + // TODO: see if we can also address this from the server side, + // or in go-connections. + // see: https://github.com/moby/moby/issues/45539 + transport.MaxIdleConns = 6 + transport.IdleConnTimeout = 30 * time.Second err := sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host) if err != nil { return nil, err @@ -296,8 +306,7 @@ func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) s var apiPath string _ = cli.checkVersion(ctx) if cli.version != "" { - v := strings.TrimPrefix(cli.version, "v") - apiPath = path.Join(cli.basePath, "/v"+v, p) + apiPath = path.Join(cli.basePath, "/v"+strings.TrimPrefix(cli.version, "v"), p) } else { apiPath = path.Join(cli.basePath, p) } @@ -442,6 +451,10 @@ func (cli *Client) dialerFromTransport() func(context.Context, string, string) ( // // ["docker dial-stdio"]: https://github.com/docker/cli/pull/1014 func (cli *Client) Dialer() func(context.Context) (net.Conn, error) { + return cli.dialer() +} + +func (cli *Client) dialer() func(context.Context) (net.Conn, error) { return func(ctx context.Context) (net.Conn, error) { if dialFn := cli.dialerFromTransport(); dialFn != nil { return dialFn(ctx, cli.proto, cli.addr) diff --git a/vendor/github.com/docker/docker/client/interface.go b/vendor/github.com/docker/docker/client/client_interfaces.go similarity index 86% rename from vendor/github.com/docker/docker/client/interface.go rename to vendor/github.com/docker/docker/client/client_interfaces.go index cc60a5d13..f70d8ffa0 100644 --- a/vendor/github.com/docker/docker/client/interface.go +++ b/vendor/github.com/docker/docker/client/client_interfaces.go @@ -20,17 +20,23 @@ import ( ) // CommonAPIClient is the common methods between stable and experimental versions of APIClient. -type CommonAPIClient interface { +// +// Deprecated: use [APIClient] instead. This type will be an alias for [APIClient] in the next release, and removed after. +type CommonAPIClient = stableAPIClient + +// APIClient is an interface that clients that talk with a docker server must implement. +type APIClient interface { + stableAPIClient + CheckpointAPIClient // CheckpointAPIClient is still experimental. +} + +type stableAPIClient interface { ConfigAPIClient ContainerAPIClient DistributionAPIClient ImageAPIClient - NodeAPIClient NetworkAPIClient PluginAPIClient - ServiceAPIClient - SwarmAPIClient - SecretAPIClient SystemAPIClient VolumeAPIClient ClientVersion() string @@ -39,27 +45,43 @@ type CommonAPIClient interface { ServerVersion(ctx context.Context) (types.Version, error) NegotiateAPIVersion(ctx context.Context) NegotiateAPIVersionPing(types.Ping) - DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) + HijackDialer Dialer() func(context.Context) (net.Conn, error) Close() error + SwarmManagementAPIClient +} + +// SwarmManagementAPIClient defines all methods for managing Swarm-specific +// objects. +type SwarmManagementAPIClient interface { + SwarmAPIClient + NodeAPIClient + ServiceAPIClient + SecretAPIClient + ConfigAPIClient +} + +// HijackDialer defines methods for a hijack dialer. +type HijackDialer interface { + DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) } // ContainerAPIClient defines API client methods for the containers type ContainerAPIClient interface { ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (types.HijackedResponse, error) - ContainerCommit(ctx context.Context, container string, options container.CommitOptions) (types.IDResponse, error) + ContainerCommit(ctx context.Context, container string, options container.CommitOptions) (container.CommitResponse, error) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error) ContainerExecAttach(ctx context.Context, execID string, options container.ExecAttachOptions) (types.HijackedResponse, error) - ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (types.IDResponse, error) + ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (container.ExecCreateResponse, error) ContainerExecInspect(ctx context.Context, execID string) (container.ExecInspect, error) ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error ContainerExecStart(ctx context.Context, execID string, options container.ExecStartOptions) error ContainerExport(ctx context.Context, container string) (io.ReadCloser, error) - ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) - ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error) + ContainerInspect(ctx context.Context, container string) (container.InspectResponse, error) + ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (container.InspectResponse, []byte, error) ContainerKill(ctx context.Context, container, signal string) error - ContainerList(ctx context.Context, options container.ListOptions) ([]types.Container, error) + ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error) ContainerLogs(ctx context.Context, container string, options container.LogsOptions) (io.ReadCloser, error) ContainerPause(ctx context.Context, container string) error ContainerRemove(ctx context.Context, container string, options container.RemoveOptions) error @@ -71,9 +93,9 @@ type ContainerAPIClient interface { ContainerStatsOneShot(ctx context.Context, container string) (container.StatsResponseReader, error) ContainerStart(ctx context.Context, container string, options container.StartOptions) error ContainerStop(ctx context.Context, container string, options container.StopOptions) error - ContainerTop(ctx context.Context, container string, arguments []string) (container.ContainerTopOKBody, error) + ContainerTop(ctx context.Context, container string, arguments []string) (container.TopResponse, error) ContainerUnpause(ctx context.Context, container string) error - ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) + ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (container.UpdateResponse, error) ContainerWait(ctx context.Context, container string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, container.PathStat, error) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options container.CopyToContainerOptions) error @@ -91,18 +113,30 @@ type ImageAPIClient interface { BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) BuildCancel(ctx context.Context, id string) error ImageCreate(ctx context.Context, parentReference string, options image.CreateOptions) (io.ReadCloser, error) - ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error) ImageImport(ctx context.Context, source image.ImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error) - ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error) + ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) - ImageLoad(ctx context.Context, input io.Reader, quiet bool) (image.LoadResponse, error) ImagePull(ctx context.Context, ref string, options image.PullOptions) (io.ReadCloser, error) ImagePush(ctx context.Context, ref string, options image.PushOptions) (io.ReadCloser, error) ImageRemove(ctx context.Context, image string, options image.RemoveOptions) ([]image.DeleteResponse, error) ImageSearch(ctx context.Context, term string, options registry.SearchOptions) ([]registry.SearchResult, error) - ImageSave(ctx context.Context, images []string) (io.ReadCloser, error) ImageTag(ctx context.Context, image, ref string) error ImagesPrune(ctx context.Context, pruneFilter filters.Args) (image.PruneReport, error) + + ImageInspect(ctx context.Context, image string, _ ...ImageInspectOption) (image.InspectResponse, error) + ImageHistory(ctx context.Context, image string, _ ...ImageHistoryOption) ([]image.HistoryResponseItem, error) + ImageLoad(ctx context.Context, input io.Reader, _ ...ImageLoadOption) (image.LoadResponse, error) + ImageSave(ctx context.Context, images []string, _ ...ImageSaveOption) (io.ReadCloser, error) + + ImageAPIClientDeprecated +} + +// ImageAPIClientDeprecated defines deprecated methods of the ImageAPIClient. +type ImageAPIClientDeprecated interface { + // ImageInspectWithRaw returns the image information and its raw representation. + // + // Deprecated: Use [Client.ImageInspect] instead. Raw response can be obtained using the [ImageInspectWithRawResponse] option. + ImageInspectWithRaw(ctx context.Context, image string) (image.InspectResponse, []byte, error) } // NetworkAPIClient defines API client methods for the networks diff --git a/vendor/github.com/docker/docker/client/config_create.go b/vendor/github.com/docker/docker/client/config_create.go index 3deb4a8e2..c7ea6d2eb 100644 --- a/vendor/github.com/docker/docker/client/config_create.go +++ b/vendor/github.com/docker/docker/client/config_create.go @@ -20,6 +20,6 @@ func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (t return response, err } - err = json.NewDecoder(resp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/config_inspect.go b/vendor/github.com/docker/docker/client/config_inspect.go index 2c6c7cb36..679a42c76 100644 --- a/vendor/github.com/docker/docker/client/config_inspect.go +++ b/vendor/github.com/docker/docker/client/config_inspect.go @@ -11,8 +11,9 @@ import ( // ConfigInspectWithRaw returns the config information with raw data func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) { - if id == "" { - return swarm.Config{}, nil, objectNotFoundError{object: "config", id: id} + id, err := trimID("contig", id) + if err != nil { + return swarm.Config{}, nil, err } if err := cli.NewVersionError(ctx, "1.30", "config inspect"); err != nil { return swarm.Config{}, nil, err @@ -23,7 +24,7 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C return swarm.Config{}, nil, err } - body, err := io.ReadAll(resp.body) + body, err := io.ReadAll(resp.Body) if err != nil { return swarm.Config{}, nil, err } diff --git a/vendor/github.com/docker/docker/client/config_list.go b/vendor/github.com/docker/docker/client/config_list.go index 14dd3813e..7e4a8ea56 100644 --- a/vendor/github.com/docker/docker/client/config_list.go +++ b/vendor/github.com/docker/docker/client/config_list.go @@ -33,6 +33,6 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio } var configs []swarm.Config - err = json.NewDecoder(resp.body).Decode(&configs) + err = json.NewDecoder(resp.Body).Decode(&configs) return configs, err } diff --git a/vendor/github.com/docker/docker/client/config_remove.go b/vendor/github.com/docker/docker/client/config_remove.go index d05b0113a..a2955c689 100644 --- a/vendor/github.com/docker/docker/client/config_remove.go +++ b/vendor/github.com/docker/docker/client/config_remove.go @@ -4,6 +4,10 @@ import "context" // ConfigRemove removes a config. func (cli *Client) ConfigRemove(ctx context.Context, id string) error { + id, err := trimID("config", id) + if err != nil { + return err + } if err := cli.NewVersionError(ctx, "1.30", "config remove"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/client/config_update.go b/vendor/github.com/docker/docker/client/config_update.go index 6995861df..ddb219cf6 100644 --- a/vendor/github.com/docker/docker/client/config_update.go +++ b/vendor/github.com/docker/docker/client/config_update.go @@ -9,6 +9,10 @@ import ( // ConfigUpdate attempts to update a config func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error { + id, err := trimID("config", id) + if err != nil { + return err + } if err := cli.NewVersionError(ctx, "1.30", "config update"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/client/container_attach.go b/vendor/github.com/docker/docker/client/container_attach.go index 6a32e5f66..2e7a13e5c 100644 --- a/vendor/github.com/docker/docker/client/container_attach.go +++ b/vendor/github.com/docker/docker/client/container_attach.go @@ -33,7 +33,12 @@ import ( // // You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this // stream. -func (cli *Client) ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (types.HijackedResponse, error) { +func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return types.HijackedResponse{}, err + } + query := url.Values{} if options.Stream { query.Set("stream", "1") @@ -54,7 +59,7 @@ func (cli *Client) ContainerAttach(ctx context.Context, container string, option query.Set("logs", "1") } - return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, http.Header{ + return cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{ "Content-Type": {"text/plain"}, }) } diff --git a/vendor/github.com/docker/docker/client/container_commit.go b/vendor/github.com/docker/docker/client/container_commit.go index 26b3f0915..9b46a1f32 100644 --- a/vendor/github.com/docker/docker/client/container_commit.go +++ b/vendor/github.com/docker/docker/client/container_commit.go @@ -7,21 +7,25 @@ import ( "net/url" "github.com/distribution/reference" - "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" ) // ContainerCommit applies changes to a container and creates a new tagged image. -func (cli *Client) ContainerCommit(ctx context.Context, container string, options container.CommitOptions) (types.IDResponse, error) { +func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options container.CommitOptions) (container.CommitResponse, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return container.CommitResponse{}, err + } + var repository, tag string if options.Reference != "" { ref, err := reference.ParseNormalizedNamed(options.Reference) if err != nil { - return types.IDResponse{}, err + return container.CommitResponse{}, err } if _, isCanonical := ref.(reference.Canonical); isCanonical { - return types.IDResponse{}, errors.New("refusing to create a tag with a digest reference") + return container.CommitResponse{}, errors.New("refusing to create a tag with a digest reference") } ref = reference.TagNameOnly(ref) @@ -32,7 +36,7 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option } query := url.Values{} - query.Set("container", container) + query.Set("container", containerID) query.Set("repo", repository) query.Set("tag", tag) query.Set("comment", options.Comment) @@ -44,13 +48,13 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option query.Set("pause", "0") } - var response types.IDResponse + var response container.CommitResponse resp, err := cli.post(ctx, "/commit", query, options.Config, nil) defer ensureReaderClosed(resp) if err != nil { return response, err } - err = json.NewDecoder(resp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/container_copy.go b/vendor/github.com/docker/docker/client/container_copy.go index 8490a3b15..39584d375 100644 --- a/vendor/github.com/docker/docker/client/container_copy.go +++ b/vendor/github.com/docker/docker/client/container_copy.go @@ -16,21 +16,30 @@ import ( // ContainerStatPath returns stat information about a path inside the container filesystem. func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path string) (container.PathStat, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return container.PathStat{}, err + } + query := url.Values{} query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API. - urlStr := "/containers/" + containerID + "/archive" - response, err := cli.head(ctx, urlStr, query, nil) - defer ensureReaderClosed(response) + resp, err := cli.head(ctx, "/containers/"+containerID+"/archive", query, nil) + defer ensureReaderClosed(resp) if err != nil { return container.PathStat{}, err } - return getContainerPathStatFromHeader(response.header) + return getContainerPathStatFromHeader(resp.Header) } // CopyToContainer copies content into the container filesystem. // Note that `content` must be a Reader for a TAR archive func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader, options container.CopyToContainerOptions) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + query := url.Values{} query.Set("path", filepath.ToSlash(dstPath)) // Normalize the paths used in the API. // Do not allow for an existing directory to be overwritten by a non-directory and vice versa. @@ -42,9 +51,7 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str query.Set("copyUIDGID", "true") } - apiPath := "/containers/" + containerID + "/archive" - - response, err := cli.putRaw(ctx, apiPath, query, content, nil) + response, err := cli.putRaw(ctx, "/containers/"+containerID+"/archive", query, content, nil) defer ensureReaderClosed(response) if err != nil { return err @@ -56,11 +63,15 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str // CopyFromContainer gets the content from the container and returns it as a Reader // for a TAR archive to manipulate it in the host. It's up to the caller to close the reader. func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, container.PathStat, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return nil, container.PathStat{}, err + } + query := make(url.Values, 1) query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API. - apiPath := "/containers/" + containerID + "/archive" - response, err := cli.get(ctx, apiPath, query, nil) + resp, err := cli.get(ctx, "/containers/"+containerID+"/archive", query, nil) if err != nil { return nil, container.PathStat{}, err } @@ -71,11 +82,11 @@ func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath s // copy it locally. Along with the stat info about the local destination, // we have everything we need to handle the multiple possibilities there // can be when copying a file/dir from one location to another file/dir. - stat, err := getContainerPathStatFromHeader(response.header) + stat, err := getContainerPathStatFromHeader(resp.Header) if err != nil { return nil, stat, fmt.Errorf("unable to get resource stat from response: %s", err) } - return response.body, stat, err + return resp.Body, stat, err } func getContainerPathStatFromHeader(header http.Header) (container.PathStat, error) { diff --git a/vendor/github.com/docker/docker/client/container_create.go b/vendor/github.com/docker/docker/client/container_create.go index 5442d4267..9b8616f76 100644 --- a/vendor/github.com/docker/docker/client/container_create.go +++ b/vendor/github.com/docker/docker/client/container_create.go @@ -5,6 +5,8 @@ import ( "encoding/json" "net/url" "path" + "sort" + "strings" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" @@ -12,12 +14,6 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) -type configWrapper struct { - *container.Config - HostConfig *container.HostConfig - NetworkingConfig *network.NetworkingConfig -} - // ContainerCreate creates a new container based on the given configuration. // It can be associated with a name, but it's not mandatory. func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) { @@ -58,6 +54,9 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config // When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize hostConfig.ConsoleSize = [2]uint{0, 0} } + + hostConfig.CapAdd = normalizeCapabilities(hostConfig.CapAdd) + hostConfig.CapDrop = normalizeCapabilities(hostConfig.CapDrop) } // Since API 1.44, the container-wide MacAddress is deprecated and will trigger a WARNING if it's specified. @@ -74,19 +73,19 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config query.Set("name", containerName) } - body := configWrapper{ + body := container.CreateRequest{ Config: config, HostConfig: hostConfig, NetworkingConfig: networkingConfig, } - serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/containers/create", query, body, nil) + defer ensureReaderClosed(resp) if err != nil { return response, err } - err = json.NewDecoder(serverResp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } @@ -114,3 +113,42 @@ func hasEndpointSpecificMacAddress(networkingConfig *network.NetworkingConfig) b } return false } + +// allCapabilities is a magic value for "all capabilities" +const allCapabilities = "ALL" + +// normalizeCapabilities normalizes capabilities to their canonical form, +// removes duplicates, and sorts the results. +// +// It is similar to [github.com/docker/docker/oci/caps.NormalizeLegacyCapabilities], +// but performs no validation based on supported capabilities. +func normalizeCapabilities(caps []string) []string { + var normalized []string + + unique := make(map[string]struct{}) + for _, c := range caps { + c = normalizeCap(c) + if _, ok := unique[c]; ok { + continue + } + unique[c] = struct{}{} + normalized = append(normalized, c) + } + + sort.Strings(normalized) + return normalized +} + +// normalizeCap normalizes a capability to its canonical format by upper-casing +// and adding a "CAP_" prefix (if not yet present). It also accepts the "ALL" +// magic-value. +func normalizeCap(cap string) string { + cap = strings.ToUpper(cap) + if cap == allCapabilities { + return cap + } + if !strings.HasPrefix(cap, "CAP_") { + cap = "CAP_" + cap + } + return cap +} diff --git a/vendor/github.com/docker/docker/client/container_diff.go b/vendor/github.com/docker/docker/client/container_diff.go index c22c819a7..52401898b 100644 --- a/vendor/github.com/docker/docker/client/container_diff.go +++ b/vendor/github.com/docker/docker/client/container_diff.go @@ -10,14 +10,21 @@ import ( // ContainerDiff shows differences in a container filesystem since it was started. func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) { - var changes []container.FilesystemChange + containerID, err := trimID("container", containerID) + if err != nil { + return nil, err + } - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) + defer ensureReaderClosed(resp) if err != nil { - return changes, err + return nil, err } - err = json.NewDecoder(serverResp.body).Decode(&changes) + var changes []container.FilesystemChange + err = json.NewDecoder(resp.Body).Decode(&changes) + if err != nil { + return nil, err + } return changes, err } diff --git a/vendor/github.com/docker/docker/client/container_exec.go b/vendor/github.com/docker/docker/client/container_exec.go index 9379448d1..a39ec7179 100644 --- a/vendor/github.com/docker/docker/client/container_exec.go +++ b/vendor/github.com/docker/docker/client/container_exec.go @@ -11,8 +11,11 @@ import ( ) // ContainerExecCreate creates a new exec configuration to run an exec process. -func (cli *Client) ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (types.IDResponse, error) { - var response types.IDResponse +func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, options container.ExecOptions) (container.ExecCreateResponse, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return container.ExecCreateResponse{}, err + } // Make sure we negotiated (if the client is configured to do so), // as code below contains API-version specific handling of options. @@ -20,22 +23,24 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, op // Normally, version-negotiation (if enabled) would not happen until // the API request is made. if err := cli.checkVersion(ctx); err != nil { - return response, err + return container.ExecCreateResponse{}, err } if err := cli.NewVersionError(ctx, "1.25", "env"); len(options.Env) != 0 && err != nil { - return response, err + return container.ExecCreateResponse{}, err } if versions.LessThan(cli.ClientVersion(), "1.42") { options.ConsoleSize = nil } - resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, options, nil) + resp, err := cli.post(ctx, "/containers/"+containerID+"/exec", nil, options, nil) defer ensureReaderClosed(resp) if err != nil { - return response, err + return container.ExecCreateResponse{}, err } - err = json.NewDecoder(resp.body).Decode(&response) + + var response container.ExecCreateResponse + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } @@ -70,7 +75,7 @@ func (cli *Client) ContainerExecInspect(ctx context.Context, execID string) (con return response, err } - err = json.NewDecoder(resp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) ensureReaderClosed(resp) return response, err } diff --git a/vendor/github.com/docker/docker/client/container_export.go b/vendor/github.com/docker/docker/client/container_export.go index d0c0a5cba..360d52763 100644 --- a/vendor/github.com/docker/docker/client/container_export.go +++ b/vendor/github.com/docker/docker/client/container_export.go @@ -10,10 +10,15 @@ import ( // and returns them as an io.ReadCloser. It's up to the caller // to close the stream. func (cli *Client) ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) { - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/export", url.Values{}, nil) + containerID, err := trimID("container", containerID) if err != nil { return nil, err } - return serverResp.body, nil + resp, err := cli.get(ctx, "/containers/"+containerID+"/export", url.Values{}, nil) + if err != nil { + return nil, err + } + + return resp.Body, nil } diff --git a/vendor/github.com/docker/docker/client/container_inspect.go b/vendor/github.com/docker/docker/client/container_inspect.go index d48f0d3a6..600031860 100644 --- a/vendor/github.com/docker/docker/client/container_inspect.go +++ b/vendor/github.com/docker/docker/client/container_inspect.go @@ -7,46 +7,50 @@ import ( "io" "net/url" - "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" ) // ContainerInspect returns the container information. -func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) { - if containerID == "" { - return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID} +func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (container.InspectResponse, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return container.InspectResponse{}, err } - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) - defer ensureReaderClosed(serverResp) + + resp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) + defer ensureReaderClosed(resp) if err != nil { - return types.ContainerJSON{}, err + return container.InspectResponse{}, err } - var response types.ContainerJSON - err = json.NewDecoder(serverResp.body).Decode(&response) + var response container.InspectResponse + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } // ContainerInspectWithRaw returns the container information and its raw representation. -func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) { - if containerID == "" { - return types.ContainerJSON{}, nil, objectNotFoundError{object: "container", id: containerID} +func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (container.InspectResponse, []byte, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return container.InspectResponse{}, nil, err } + query := url.Values{} if getSize { query.Set("size", "1") } - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) + defer ensureReaderClosed(resp) if err != nil { - return types.ContainerJSON{}, nil, err + return container.InspectResponse{}, nil, err } - body, err := io.ReadAll(serverResp.body) + body, err := io.ReadAll(resp.Body) if err != nil { - return types.ContainerJSON{}, nil, err + return container.InspectResponse{}, nil, err } - var response types.ContainerJSON + var response container.InspectResponse rdr := bytes.NewReader(body) err = json.NewDecoder(rdr).Decode(&response) return response, body, err diff --git a/vendor/github.com/docker/docker/client/container_kill.go b/vendor/github.com/docker/docker/client/container_kill.go index 7c9529f1e..22767ae68 100644 --- a/vendor/github.com/docker/docker/client/container_kill.go +++ b/vendor/github.com/docker/docker/client/container_kill.go @@ -7,6 +7,11 @@ import ( // ContainerKill terminates the container process but does not remove the container from the docker host. func (cli *Client) ContainerKill(ctx context.Context, containerID, signal string) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + query := url.Values{} if signal != "" { query.Set("signal", signal) diff --git a/vendor/github.com/docker/docker/client/container_list.go b/vendor/github.com/docker/docker/client/container_list.go index 782e1b3c6..510bcdf68 100644 --- a/vendor/github.com/docker/docker/client/container_list.go +++ b/vendor/github.com/docker/docker/client/container_list.go @@ -6,13 +6,12 @@ import ( "net/url" "strconv" - "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" ) // ContainerList returns the list of containers in the docker host. -func (cli *Client) ContainerList(ctx context.Context, options container.ListOptions) ([]types.Container, error) { +func (cli *Client) ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error) { query := url.Values{} if options.All { @@ -51,7 +50,7 @@ func (cli *Client) ContainerList(ctx context.Context, options container.ListOpti return nil, err } - var containers []types.Container - err = json.NewDecoder(resp.body).Decode(&containers) + var containers []container.Summary + err = json.NewDecoder(resp.Body).Decode(&containers) return containers, err } diff --git a/vendor/github.com/docker/docker/client/container_logs.go b/vendor/github.com/docker/docker/client/container_logs.go index 61197d840..ae30f8d10 100644 --- a/vendor/github.com/docker/docker/client/container_logs.go +++ b/vendor/github.com/docker/docker/client/container_logs.go @@ -33,7 +33,12 @@ import ( // // You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this // stream. -func (cli *Client) ContainerLogs(ctx context.Context, container string, options container.LogsOptions) (io.ReadCloser, error) { +func (cli *Client) ContainerLogs(ctx context.Context, containerID string, options container.LogsOptions) (io.ReadCloser, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return nil, err + } + query := url.Values{} if options.ShowStdout { query.Set("stdout", "1") @@ -72,9 +77,9 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options } query.Set("tail", options.Tail) - resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) + resp, err := cli.get(ctx, "/containers/"+containerID+"/logs", query, nil) if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } diff --git a/vendor/github.com/docker/docker/client/container_pause.go b/vendor/github.com/docker/docker/client/container_pause.go index 5e7271a37..5cc298401 100644 --- a/vendor/github.com/docker/docker/client/container_pause.go +++ b/vendor/github.com/docker/docker/client/container_pause.go @@ -4,6 +4,11 @@ import "context" // ContainerPause pauses the main process of a given container without terminating it. func (cli *Client) ContainerPause(ctx context.Context, containerID string) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + resp, err := cli.post(ctx, "/containers/"+containerID+"/pause", nil, nil, nil) ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/container_prune.go b/vendor/github.com/docker/docker/client/container_prune.go index 29c922da7..3176be596 100644 --- a/vendor/github.com/docker/docker/client/container_prune.go +++ b/vendor/github.com/docker/docker/client/container_prune.go @@ -11,25 +11,24 @@ import ( // ContainersPrune requests the daemon to delete unused data func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error) { - var report container.PruneReport - if err := cli.NewVersionError(ctx, "1.25", "container prune"); err != nil { - return report, err + return container.PruneReport{}, err } query, err := getFiltersQuery(pruneFilters) if err != nil { - return report, err + return container.PruneReport{}, err } - serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/containers/prune", query, nil, nil) + defer ensureReaderClosed(resp) if err != nil { - return report, err + return container.PruneReport{}, err } - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, fmt.Errorf("Error retrieving disk usage: %v", err) + var report container.PruneReport + if err := json.NewDecoder(resp.Body).Decode(&report); err != nil { + return container.PruneReport{}, fmt.Errorf("Error retrieving disk usage: %v", err) } return report, nil diff --git a/vendor/github.com/docker/docker/client/container_remove.go b/vendor/github.com/docker/docker/client/container_remove.go index 39f7b106a..6661351a9 100644 --- a/vendor/github.com/docker/docker/client/container_remove.go +++ b/vendor/github.com/docker/docker/client/container_remove.go @@ -9,6 +9,11 @@ import ( // ContainerRemove kills and removes a container from the docker host. func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options container.RemoveOptions) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + query := url.Values{} if options.RemoveVolumes { query.Set("v", "1") diff --git a/vendor/github.com/docker/docker/client/container_rename.go b/vendor/github.com/docker/docker/client/container_rename.go index 240fdf552..0a092310c 100644 --- a/vendor/github.com/docker/docker/client/container_rename.go +++ b/vendor/github.com/docker/docker/client/container_rename.go @@ -7,6 +7,11 @@ import ( // ContainerRename changes the name of a given container. func (cli *Client) ContainerRename(ctx context.Context, containerID, newContainerName string) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + query := url.Values{} query.Set("name", newContainerName) resp, err := cli.post(ctx, "/containers/"+containerID+"/rename", query, nil, nil) diff --git a/vendor/github.com/docker/docker/client/container_resize.go b/vendor/github.com/docker/docker/client/container_resize.go index 5cfd01d47..725c08ad4 100644 --- a/vendor/github.com/docker/docker/client/container_resize.go +++ b/vendor/github.com/docker/docker/client/container_resize.go @@ -10,18 +10,27 @@ import ( // ContainerResize changes the size of the tty for a container. func (cli *Client) ContainerResize(ctx context.Context, containerID string, options container.ResizeOptions) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } return cli.resize(ctx, "/containers/"+containerID, options.Height, options.Width) } // ContainerExecResize changes the size of the tty for an exec process running inside a container. func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error { + execID, err := trimID("exec", execID) + if err != nil { + return err + } return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width) } func (cli *Client) resize(ctx context.Context, basePath string, height, width uint) error { + // FIXME(thaJeztah): the API / backend accepts uint32, but container.ResizeOptions uses uint. query := url.Values{} - query.Set("h", strconv.Itoa(int(height))) - query.Set("w", strconv.Itoa(int(width))) + query.Set("h", strconv.FormatUint(uint64(height), 10)) + query.Set("w", strconv.FormatUint(uint64(width), 10)) resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil) ensureReaderClosed(resp) diff --git a/vendor/github.com/docker/docker/client/container_restart.go b/vendor/github.com/docker/docker/client/container_restart.go index 02b5079bc..50559ba6e 100644 --- a/vendor/github.com/docker/docker/client/container_restart.go +++ b/vendor/github.com/docker/docker/client/container_restart.go @@ -13,6 +13,11 @@ import ( // It makes the daemon wait for the container to be up again for // a specific amount of time, given the timeout. func (cli *Client) ContainerRestart(ctx context.Context, containerID string, options container.StopOptions) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + query := url.Values{} if options.Timeout != nil { query.Set("t", strconv.Itoa(*options.Timeout)) diff --git a/vendor/github.com/docker/docker/client/container_start.go b/vendor/github.com/docker/docker/client/container_start.go index 33ba85f24..b81ed3ebc 100644 --- a/vendor/github.com/docker/docker/client/container_start.go +++ b/vendor/github.com/docker/docker/client/container_start.go @@ -9,6 +9,11 @@ import ( // ContainerStart sends a request to the docker daemon to start a container. func (cli *Client) ContainerStart(ctx context.Context, containerID string, options container.StartOptions) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + query := url.Values{} if len(options.CheckpointID) != 0 { query.Set("checkpoint", options.CheckpointID) diff --git a/vendor/github.com/docker/docker/client/container_stats.go b/vendor/github.com/docker/docker/client/container_stats.go index b5641daee..a66b90cb2 100644 --- a/vendor/github.com/docker/docker/client/container_stats.go +++ b/vendor/github.com/docker/docker/client/container_stats.go @@ -10,6 +10,11 @@ import ( // ContainerStats returns near realtime stats for a given container. // It's up to the caller to close the io.ReadCloser returned. func (cli *Client) ContainerStats(ctx context.Context, containerID string, stream bool) (container.StatsResponseReader, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return container.StatsResponseReader{}, err + } + query := url.Values{} query.Set("stream", "0") if stream { @@ -22,14 +27,19 @@ func (cli *Client) ContainerStats(ctx context.Context, containerID string, strea } return container.StatsResponseReader{ - Body: resp.body, - OSType: getDockerOS(resp.header.Get("Server")), + Body: resp.Body, + OSType: getDockerOS(resp.Header.Get("Server")), }, nil } // ContainerStatsOneShot gets a single stat entry from a container. // It differs from `ContainerStats` in that the API should not wait to prime the stats func (cli *Client) ContainerStatsOneShot(ctx context.Context, containerID string) (container.StatsResponseReader, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return container.StatsResponseReader{}, err + } + query := url.Values{} query.Set("stream", "0") query.Set("one-shot", "1") @@ -40,7 +50,7 @@ func (cli *Client) ContainerStatsOneShot(ctx context.Context, containerID string } return container.StatsResponseReader{ - Body: resp.body, - OSType: getDockerOS(resp.header.Get("Server")), + Body: resp.Body, + OSType: getDockerOS(resp.Header.Get("Server")), }, nil } diff --git a/vendor/github.com/docker/docker/client/container_stop.go b/vendor/github.com/docker/docker/client/container_stop.go index 7c98a354b..eb0129ce3 100644 --- a/vendor/github.com/docker/docker/client/container_stop.go +++ b/vendor/github.com/docker/docker/client/container_stop.go @@ -17,6 +17,11 @@ import ( // otherwise the engine default. A negative timeout value can be specified, // meaning no timeout, i.e. no forceful termination is performed. func (cli *Client) ContainerStop(ctx context.Context, containerID string, options container.StopOptions) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + query := url.Values{} if options.Timeout != nil { query.Set("t", strconv.Itoa(*options.Timeout)) diff --git a/vendor/github.com/docker/docker/client/container_top.go b/vendor/github.com/docker/docker/client/container_top.go index a5b78999b..12c8b78f6 100644 --- a/vendor/github.com/docker/docker/client/container_top.go +++ b/vendor/github.com/docker/docker/client/container_top.go @@ -10,8 +10,12 @@ import ( ) // ContainerTop shows process information from within a container. -func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (container.ContainerTopOKBody, error) { - var response container.ContainerTopOKBody +func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (container.TopResponse, error) { + containerID, err := trimID("container", containerID) + if err != nil { + return container.TopResponse{}, err + } + query := url.Values{} if len(arguments) > 0 { query.Set("ps_args", strings.Join(arguments, " ")) @@ -20,9 +24,10 @@ func (cli *Client) ContainerTop(ctx context.Context, containerID string, argumen resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) defer ensureReaderClosed(resp) if err != nil { - return response, err + return container.TopResponse{}, err } - err = json.NewDecoder(resp.body).Decode(&response) + var response container.TopResponse + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/container_unpause.go b/vendor/github.com/docker/docker/client/container_unpause.go index 1d8f87316..f602549bb 100644 --- a/vendor/github.com/docker/docker/client/container_unpause.go +++ b/vendor/github.com/docker/docker/client/container_unpause.go @@ -4,6 +4,11 @@ import "context" // ContainerUnpause resumes the process execution within a container func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error { + containerID, err := trimID("container", containerID) + if err != nil { + return err + } + resp, err := cli.post(ctx, "/containers/"+containerID+"/unpause", nil, nil, nil) ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/container_update.go b/vendor/github.com/docker/docker/client/container_update.go index bf68a5300..7f0cf6276 100644 --- a/vendor/github.com/docker/docker/client/container_update.go +++ b/vendor/github.com/docker/docker/client/container_update.go @@ -8,14 +8,19 @@ import ( ) // ContainerUpdate updates the resources of a container. -func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) { - var response container.ContainerUpdateOKBody - serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) - defer ensureReaderClosed(serverResp) +func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.UpdateResponse, error) { + containerID, err := trimID("container", containerID) if err != nil { - return response, err + return container.UpdateResponse{}, err } - err = json.NewDecoder(serverResp.body).Decode(&response) + resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) + defer ensureReaderClosed(resp) + if err != nil { + return container.UpdateResponse{}, err + } + + var response container.UpdateResponse + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/container_wait.go b/vendor/github.com/docker/docker/client/container_wait.go index 8bb6be0a1..bda4a9eee 100644 --- a/vendor/github.com/docker/docker/client/container_wait.go +++ b/vendor/github.com/docker/docker/client/container_wait.go @@ -33,6 +33,12 @@ func (cli *Client) ContainerWait(ctx context.Context, containerID string, condit resultC := make(chan container.WaitResponse) errC := make(chan error, 1) + containerID, err := trimID("container", containerID) + if err != nil { + errC <- err + return resultC, errC + } + // Make sure we negotiated (if the client is configured to do so), // as code below contains API-version specific handling of options. // @@ -61,9 +67,8 @@ func (cli *Client) ContainerWait(ctx context.Context, containerID string, condit go func() { defer ensureReaderClosed(resp) - body := resp.body responseText := bytes.NewBuffer(nil) - stream := io.TeeReader(body, responseText) + stream := io.TeeReader(resp.Body, responseText) var res container.WaitResponse if err := json.NewDecoder(stream).Decode(&res); err != nil { @@ -105,7 +110,7 @@ func (cli *Client) legacyContainerWait(ctx context.Context, containerID string) defer ensureReaderClosed(resp) var res container.WaitResponse - if err := json.NewDecoder(resp.body).Decode(&res); err != nil { + if err := json.NewDecoder(resp.Body).Decode(&res); err != nil { errC <- err return } diff --git a/vendor/github.com/docker/docker/client/disk_usage.go b/vendor/github.com/docker/docker/client/disk_usage.go index ba0d92e9e..ed788125c 100644 --- a/vendor/github.com/docker/docker/client/disk_usage.go +++ b/vendor/github.com/docker/docker/client/disk_usage.go @@ -19,14 +19,14 @@ func (cli *Client) DiskUsage(ctx context.Context, options types.DiskUsageOptions } } - serverResp, err := cli.get(ctx, "/system/df", query, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/system/df", query, nil) + defer ensureReaderClosed(resp) if err != nil { return types.DiskUsage{}, err } var du types.DiskUsage - if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil { + if err := json.NewDecoder(resp.Body).Decode(&du); err != nil { return types.DiskUsage{}, fmt.Errorf("Error retrieving disk usage: %v", err) } return du, nil diff --git a/vendor/github.com/docker/docker/client/distribution_inspect.go b/vendor/github.com/docker/docker/client/distribution_inspect.go index 68e6ec5ed..b8654b24f 100644 --- a/vendor/github.com/docker/docker/client/distribution_inspect.go +++ b/vendor/github.com/docker/docker/client/distribution_inspect.go @@ -11,14 +11,12 @@ import ( // DistributionInspect returns the image digest with the full manifest. func (cli *Client) DistributionInspect(ctx context.Context, imageRef, encodedRegistryAuth string) (registry.DistributionInspect, error) { - // Contact the registry to retrieve digest and platform information - var distributionInspect registry.DistributionInspect if imageRef == "" { - return distributionInspect, objectNotFoundError{object: "distribution", id: imageRef} + return registry.DistributionInspect{}, objectNotFoundError{object: "distribution", id: imageRef} } if err := cli.NewVersionError(ctx, "1.30", "distribution inspect"); err != nil { - return distributionInspect, err + return registry.DistributionInspect{}, err } var headers http.Header @@ -28,12 +26,14 @@ func (cli *Client) DistributionInspect(ctx context.Context, imageRef, encodedReg } } + // Contact the registry to retrieve digest and platform information resp, err := cli.get(ctx, "/distribution/"+imageRef+"/json", url.Values{}, headers) defer ensureReaderClosed(resp) if err != nil { - return distributionInspect, err + return registry.DistributionInspect{}, err } - err = json.NewDecoder(resp.body).Decode(&distributionInspect) + var distributionInspect registry.DistributionInspect + err = json.NewDecoder(resp.Body).Decode(&distributionInspect) return distributionInspect, err } diff --git a/vendor/github.com/docker/docker/client/errors.go b/vendor/github.com/docker/docker/client/errors.go index 0d01e243f..609f92ce6 100644 --- a/vendor/github.com/docker/docker/client/errors.go +++ b/vendor/github.com/docker/docker/client/errors.go @@ -2,11 +2,11 @@ package client // import "github.com/docker/docker/client" import ( "context" + "errors" "fmt" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/errdefs" - "github.com/pkg/errors" ) // errConnectionFailed implements an error returned when connection failed. @@ -29,10 +29,18 @@ func IsErrConnectionFailed(err error) bool { } // ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed. +// +// Deprecated: this function was only used internally, and will be removed in the next release. func ErrorConnectionFailed(host string) error { + return connectionFailed(host) +} + +// connectionFailed returns an error with host in the error message when connection +// to docker daemon failed. +func connectionFailed(host string) error { var err error if host == "" { - err = fmt.Errorf("Cannot connect to the Docker daemon. Is the docker daemon running on this host?") + err = errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?") } else { err = fmt.Errorf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", host) } diff --git a/vendor/github.com/docker/docker/client/events.go b/vendor/github.com/docker/docker/client/events.go index d3ab26bed..c71d2a088 100644 --- a/vendor/github.com/docker/docker/client/events.go +++ b/vendor/github.com/docker/docker/client/events.go @@ -36,9 +36,9 @@ func (cli *Client) Events(ctx context.Context, options events.ListOptions) (<-ch errs <- err return } - defer resp.body.Close() + defer resp.Body.Close() - decoder := json.NewDecoder(resp.body) + decoder := json.NewDecoder(resp.Body) close(started) for { diff --git a/vendor/github.com/docker/docker/client/hijack.go b/vendor/github.com/docker/docker/client/hijack.go index 839d4c5cd..2c78fad00 100644 --- a/vendor/github.com/docker/docker/client/hijack.go +++ b/vendor/github.com/docker/docker/client/hijack.go @@ -25,12 +25,17 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu if err != nil { return types.HijackedResponse{}, err } - conn, mediaType, err := cli.setupHijackConn(req, "tcp") + conn, mediaType, err := setupHijackConn(cli.dialer(), req, "tcp") if err != nil { return types.HijackedResponse{}, err } - return types.NewHijackedResponse(conn, mediaType), err + if versions.LessThan(cli.ClientVersion(), "1.42") { + // Prior to 1.42, Content-Type is always set to raw-stream and not relevant + mediaType = "" + } + + return types.NewHijackedResponse(conn, mediaType), nil } // DialHijack returns a hijacked connection with negotiated protocol proto. @@ -41,16 +46,15 @@ func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[s } req = cli.addHeaders(req, meta) - conn, _, err := cli.setupHijackConn(req, proto) + conn, _, err := setupHijackConn(cli.Dialer(), req, proto) return conn, err } -func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn, _ string, retErr error) { +func setupHijackConn(dialer func(context.Context) (net.Conn, error), req *http.Request, proto string) (_ net.Conn, _ string, retErr error) { ctx := req.Context() req.Header.Set("Connection", "Upgrade") req.Header.Set("Upgrade", proto) - dialer := cli.Dialer() conn, err := dialer(ctx) if err != nil { return nil, "", errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?") @@ -96,13 +100,7 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn, hc.r.Reset(nil) } - var mediaType string - if versions.GreaterThanOrEqualTo(cli.ClientVersion(), "1.42") { - // Prior to 1.42, Content-Type is always set to raw-stream and not relevant - mediaType = resp.Header.Get("Content-Type") - } - - return conn, mediaType, nil + return conn, resp.Header.Get("Content-Type"), nil } // hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case diff --git a/vendor/github.com/docker/docker/client/image_build.go b/vendor/github.com/docker/docker/client/image_build.go index d294ddc8b..6e2a40687 100644 --- a/vendor/github.com/docker/docker/client/image_build.go +++ b/vendor/github.com/docker/docker/client/image_build.go @@ -12,6 +12,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" ) // ImageBuild sends a request to the daemon to build images. @@ -32,22 +33,27 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf)) headers.Set("Content-Type", "application/x-tar") - serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers) + resp, err := cli.postRaw(ctx, "/build", query, buildContext, headers) if err != nil { return types.ImageBuildResponse{}, err } return types.ImageBuildResponse{ - Body: serverResp.body, - OSType: getDockerOS(serverResp.header.Get("Server")), + Body: resp.Body, + OSType: getDockerOS(resp.Header.Get("Server")), }, nil } func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.ImageBuildOptions) (url.Values, error) { - query := url.Values{ - "t": options.Tags, - "securityopt": options.SecurityOpt, - "extrahosts": options.ExtraHosts, + query := url.Values{} + if len(options.Tags) > 0 { + query["t"] = options.Tags + } + if len(options.SecurityOpt) > 0 { + query["securityopt"] = options.SecurityOpt + } + if len(options.ExtraHosts) > 0 { + query["extrahosts"] = options.ExtraHosts } if options.SuppressOutput { query.Set("q", "1") @@ -58,9 +64,11 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I if options.NoCache { query.Set("nocache", "1") } - if options.Remove { - query.Set("rm", "1") - } else { + if !options.Remove { + // only send value when opting out because the daemon's default is + // to remove intermediate containers after a successful build, + // + // TODO(thaJeztah): deprecate "Remove" option, and provide a "NoRemove" or "Keep" option instead. query.Set("rm", "0") } @@ -83,42 +91,70 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I query.Set("isolation", string(options.Isolation)) } - query.Set("cpusetcpus", options.CPUSetCPUs) - query.Set("networkmode", options.NetworkMode) - query.Set("cpusetmems", options.CPUSetMems) - query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10)) - query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10)) - query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10)) - query.Set("memory", strconv.FormatInt(options.Memory, 10)) - query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10)) - query.Set("cgroupparent", options.CgroupParent) - query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10)) - query.Set("dockerfile", options.Dockerfile) - query.Set("target", options.Target) - - ulimitsJSON, err := json.Marshal(options.Ulimits) - if err != nil { - return query, err + if options.CPUSetCPUs != "" { + query.Set("cpusetcpus", options.CPUSetCPUs) } - query.Set("ulimits", string(ulimitsJSON)) - - buildArgsJSON, err := json.Marshal(options.BuildArgs) - if err != nil { - return query, err + if options.NetworkMode != "" && options.NetworkMode != network.NetworkDefault { + query.Set("networkmode", options.NetworkMode) } - query.Set("buildargs", string(buildArgsJSON)) - - labelsJSON, err := json.Marshal(options.Labels) - if err != nil { - return query, err + if options.CPUSetMems != "" { + query.Set("cpusetmems", options.CPUSetMems) } - query.Set("labels", string(labelsJSON)) - - cacheFromJSON, err := json.Marshal(options.CacheFrom) - if err != nil { - return query, err + if options.CPUShares != 0 { + query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10)) + } + if options.CPUQuota != 0 { + query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10)) + } + if options.CPUPeriod != 0 { + query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10)) + } + if options.Memory != 0 { + query.Set("memory", strconv.FormatInt(options.Memory, 10)) + } + if options.MemorySwap != 0 { + query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10)) + } + if options.CgroupParent != "" { + query.Set("cgroupparent", options.CgroupParent) + } + if options.ShmSize != 0 { + query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10)) + } + if options.Dockerfile != "" { + query.Set("dockerfile", options.Dockerfile) + } + if options.Target != "" { + query.Set("target", options.Target) + } + if len(options.Ulimits) != 0 { + ulimitsJSON, err := json.Marshal(options.Ulimits) + if err != nil { + return query, err + } + query.Set("ulimits", string(ulimitsJSON)) + } + if len(options.BuildArgs) != 0 { + buildArgsJSON, err := json.Marshal(options.BuildArgs) + if err != nil { + return query, err + } + query.Set("buildargs", string(buildArgsJSON)) + } + if len(options.Labels) != 0 { + labelsJSON, err := json.Marshal(options.Labels) + if err != nil { + return query, err + } + query.Set("labels", string(labelsJSON)) + } + if len(options.CacheFrom) != 0 { + cacheFromJSON, err := json.Marshal(options.CacheFrom) + if err != nil { + return query, err + } + query.Set("cachefrom", string(cacheFromJSON)) } - query.Set("cachefrom", string(cacheFromJSON)) if options.SessionID != "" { query.Set("session", options.SessionID) } @@ -131,7 +167,9 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I if options.BuildID != "" { query.Set("buildid", options.BuildID) } - query.Set("version", string(options.Version)) + if options.Version != "" { + query.Set("version", string(options.Version)) + } if options.Outputs != nil { outputsJSON, err := json.Marshal(options.Outputs) diff --git a/vendor/github.com/docker/docker/client/image_create.go b/vendor/github.com/docker/docker/client/image_create.go index 7c7873dca..0357051e7 100644 --- a/vendor/github.com/docker/docker/client/image_create.go +++ b/vendor/github.com/docker/docker/client/image_create.go @@ -30,10 +30,10 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } -func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { +func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (*http.Response, error) { return cli.post(ctx, "/images/create", query, nil, http.Header{ registry.AuthHeader: {registryAuth}, }) diff --git a/vendor/github.com/docker/docker/client/image_history.go b/vendor/github.com/docker/docker/client/image_history.go index b5bea10d8..49381fb83 100644 --- a/vendor/github.com/docker/docker/client/image_history.go +++ b/vendor/github.com/docker/docker/client/image_history.go @@ -3,20 +3,54 @@ package client // import "github.com/docker/docker/client" import ( "context" "encoding/json" + "fmt" "net/url" "github.com/docker/docker/api/types/image" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) +// ImageHistoryWithPlatform sets the platform for the image history operation. +func ImageHistoryWithPlatform(platform ocispec.Platform) ImageHistoryOption { + return imageHistoryOptionFunc(func(opt *imageHistoryOpts) error { + if opt.apiOptions.Platform != nil { + return fmt.Errorf("platform already set to %s", *opt.apiOptions.Platform) + } + opt.apiOptions.Platform = &platform + return nil + }) +} + // ImageHistory returns the changes in an image in history format. -func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) { - var history []image.HistoryResponseItem - serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil) - defer ensureReaderClosed(serverResp) +func (cli *Client) ImageHistory(ctx context.Context, imageID string, historyOpts ...ImageHistoryOption) ([]image.HistoryResponseItem, error) { + query := url.Values{} + + var opts imageHistoryOpts + for _, o := range historyOpts { + if err := o.Apply(&opts); err != nil { + return nil, err + } + } + + if opts.apiOptions.Platform != nil { + if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { + return nil, err + } + + p, err := encodePlatform(opts.apiOptions.Platform) + if err != nil { + return nil, err + } + query.Set("platform", p) + } + + resp, err := cli.get(ctx, "/images/"+imageID+"/history", query, nil) + defer ensureReaderClosed(resp) if err != nil { - return history, err + return nil, err } - err = json.NewDecoder(serverResp.body).Decode(&history) + var history []image.HistoryResponseItem + err = json.NewDecoder(resp.Body).Decode(&history) return history, err } diff --git a/vendor/github.com/docker/docker/client/image_history_opts.go b/vendor/github.com/docker/docker/client/image_history_opts.go new file mode 100644 index 000000000..6d3494dd0 --- /dev/null +++ b/vendor/github.com/docker/docker/client/image_history_opts.go @@ -0,0 +1,19 @@ +package client + +import ( + "github.com/docker/docker/api/types/image" +) + +// ImageHistoryOption is a type representing functional options for the image history operation. +type ImageHistoryOption interface { + Apply(*imageHistoryOpts) error +} +type imageHistoryOptionFunc func(opt *imageHistoryOpts) error + +func (f imageHistoryOptionFunc) Apply(o *imageHistoryOpts) error { + return f(o) +} + +type imageHistoryOpts struct { + apiOptions image.HistoryOptions +} diff --git a/vendor/github.com/docker/docker/client/image_import.go b/vendor/github.com/docker/docker/client/image_import.go index 43d55eda8..5849d85bd 100644 --- a/vendor/github.com/docker/docker/client/image_import.go +++ b/vendor/github.com/docker/docker/client/image_import.go @@ -21,10 +21,18 @@ func (cli *Client) ImageImport(ctx context.Context, source image.ImportSource, r } query := url.Values{} - query.Set("fromSrc", source.SourceName) - query.Set("repo", ref) - query.Set("tag", options.Tag) - query.Set("message", options.Message) + if source.SourceName != "" { + query.Set("fromSrc", source.SourceName) + } + if ref != "" { + query.Set("repo", ref) + } + if options.Tag != "" { + query.Set("tag", options.Tag) + } + if options.Message != "" { + query.Set("message", options.Message) + } if options.Platform != "" { query.Set("platform", strings.ToLower(options.Platform)) } @@ -36,5 +44,5 @@ func (cli *Client) ImageImport(ctx context.Context, source image.ImportSource, r if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } diff --git a/vendor/github.com/docker/docker/client/image_inspect.go b/vendor/github.com/docker/docker/client/image_inspect.go index 1de10e5a0..116119546 100644 --- a/vendor/github.com/docker/docker/client/image_inspect.go +++ b/vendor/github.com/docker/docker/client/image_inspect.go @@ -4,29 +4,62 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io" + "net/url" - "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/image" ) -// ImageInspectWithRaw returns the image information and its raw representation. -func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) { +// ImageInspect returns the image information. +func (cli *Client) ImageInspect(ctx context.Context, imageID string, inspectOpts ...ImageInspectOption) (image.InspectResponse, error) { if imageID == "" { - return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID} + return image.InspectResponse{}, objectNotFoundError{object: "image", id: imageID} } - serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return types.ImageInspect{}, nil, err + + var opts imageInspectOpts + for _, opt := range inspectOpts { + if err := opt.Apply(&opts); err != nil { + return image.InspectResponse{}, fmt.Errorf("error applying image inspect option: %w", err) + } } - body, err := io.ReadAll(serverResp.body) + query := url.Values{} + if opts.apiOptions.Manifests { + if err := cli.NewVersionError(ctx, "1.48", "manifests"); err != nil { + return image.InspectResponse{}, err + } + query.Set("manifests", "1") + } + + resp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil) + defer ensureReaderClosed(resp) if err != nil { - return types.ImageInspect{}, nil, err + return image.InspectResponse{}, err + } + + buf := opts.raw + if buf == nil { + buf = &bytes.Buffer{} } - var response types.ImageInspect - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err + if _, err := io.Copy(buf, resp.Body); err != nil { + return image.InspectResponse{}, err + } + + var response image.InspectResponse + err = json.Unmarshal(buf.Bytes(), &response) + return response, err +} + +// ImageInspectWithRaw returns the image information and its raw representation. +// +// Deprecated: Use [Client.ImageInspect] instead. Raw response can be obtained using the [ImageInspectWithRawResponse] option. +func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (image.InspectResponse, []byte, error) { + var buf bytes.Buffer + resp, err := cli.ImageInspect(ctx, imageID, ImageInspectWithRawResponse(&buf)) + if err != nil { + return image.InspectResponse{}, nil, err + } + return resp, buf.Bytes(), err } diff --git a/vendor/github.com/docker/docker/client/image_inspect_opts.go b/vendor/github.com/docker/docker/client/image_inspect_opts.go new file mode 100644 index 000000000..2607f3678 --- /dev/null +++ b/vendor/github.com/docker/docker/client/image_inspect_opts.go @@ -0,0 +1,50 @@ +package client + +import ( + "bytes" + + "github.com/docker/docker/api/types/image" +) + +// ImageInspectOption is a type representing functional options for the image inspect operation. +type ImageInspectOption interface { + Apply(*imageInspectOpts) error +} +type imageInspectOptionFunc func(opt *imageInspectOpts) error + +func (f imageInspectOptionFunc) Apply(o *imageInspectOpts) error { + return f(o) +} + +// ImageInspectWithRawResponse instructs the client to additionally store the +// raw inspect response in the provided buffer. +func ImageInspectWithRawResponse(raw *bytes.Buffer) ImageInspectOption { + return imageInspectOptionFunc(func(opts *imageInspectOpts) error { + opts.raw = raw + return nil + }) +} + +// ImageInspectWithManifests sets manifests API option for the image inspect operation. +// This option is only available for API version 1.48 and up. +// With this option set, the image inspect operation response will have the +// [image.InspectResponse.Manifests] field populated if the server is multi-platform capable. +func ImageInspectWithManifests(manifests bool) ImageInspectOption { + return imageInspectOptionFunc(func(clientOpts *imageInspectOpts) error { + clientOpts.apiOptions.Manifests = manifests + return nil + }) +} + +// ImageInspectWithAPIOpts sets the API options for the image inspect operation. +func ImageInspectWithAPIOpts(opts image.InspectOptions) ImageInspectOption { + return imageInspectOptionFunc(func(clientOpts *imageInspectOpts) error { + clientOpts.apiOptions = opts + return nil + }) +} + +type imageInspectOpts struct { + raw *bytes.Buffer + apiOptions image.InspectOptions +} diff --git a/vendor/github.com/docker/docker/client/image_list.go b/vendor/github.com/docker/docker/client/image_list.go index a9cc1e21e..e1911eb7e 100644 --- a/vendor/github.com/docker/docker/client/image_list.go +++ b/vendor/github.com/docker/docker/client/image_list.go @@ -11,6 +11,11 @@ import ( ) // ImageList returns a list of images in the docker host. +// +// Experimental: Setting the [options.Manifest] will populate +// [image.Summary.Manifests] with information about image manifests. +// This is experimental and might change in the future without any backward +// compatibility. func (cli *Client) ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) { var images []image.Summary @@ -47,13 +52,16 @@ func (cli *Client) ImageList(ctx context.Context, options image.ListOptions) ([] if options.SharedSize && versions.GreaterThanOrEqualTo(cli.version, "1.42") { query.Set("shared-size", "1") } + if options.Manifests && versions.GreaterThanOrEqualTo(cli.version, "1.47") { + query.Set("manifests", "1") + } - serverResp, err := cli.get(ctx, "/images/json", query, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/images/json", query, nil) + defer ensureReaderClosed(resp) if err != nil { return images, err } - err = json.NewDecoder(serverResp.body).Decode(&images) + err = json.NewDecoder(resp.Body).Decode(&images) return images, err } diff --git a/vendor/github.com/docker/docker/client/image_load.go b/vendor/github.com/docker/docker/client/image_load.go index c68f0013e..d83877d4b 100644 --- a/vendor/github.com/docker/docker/client/image_load.go +++ b/vendor/github.com/docker/docker/client/image_load.go @@ -12,20 +12,43 @@ import ( // ImageLoad loads an image in the docker host from the client host. // It's up to the caller to close the io.ReadCloser in the // ImageLoadResponse returned by this function. -func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (image.LoadResponse, error) { - v := url.Values{} - v.Set("quiet", "0") - if quiet { - v.Set("quiet", "1") +// +// Platform is an optional parameter that specifies the platform to load from +// the provided multi-platform image. This is only has effect if the input image +// is a multi-platform image. +func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, loadOpts ...ImageLoadOption) (image.LoadResponse, error) { + var opts imageLoadOpts + for _, opt := range loadOpts { + if err := opt.Apply(&opts); err != nil { + return image.LoadResponse{}, err + } } - resp, err := cli.postRaw(ctx, "/images/load", v, input, http.Header{ + + query := url.Values{} + query.Set("quiet", "0") + if opts.apiOptions.Quiet { + query.Set("quiet", "1") + } + if len(opts.apiOptions.Platforms) > 0 { + if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { + return image.LoadResponse{}, err + } + + p, err := encodePlatforms(opts.apiOptions.Platforms...) + if err != nil { + return image.LoadResponse{}, err + } + query["platform"] = p + } + + resp, err := cli.postRaw(ctx, "/images/load", query, input, http.Header{ "Content-Type": {"application/x-tar"}, }) if err != nil { return image.LoadResponse{}, err } return image.LoadResponse{ - Body: resp.body, - JSON: resp.header.Get("Content-Type") == "application/json", + Body: resp.Body, + JSON: resp.Header.Get("Content-Type") == "application/json", }, nil } diff --git a/vendor/github.com/docker/docker/client/image_load_opts.go b/vendor/github.com/docker/docker/client/image_load_opts.go new file mode 100644 index 000000000..ebcedd41f --- /dev/null +++ b/vendor/github.com/docker/docker/client/image_load_opts.go @@ -0,0 +1,41 @@ +package client + +import ( + "fmt" + + "github.com/docker/docker/api/types/image" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +// ImageLoadOption is a type representing functional options for the image load operation. +type ImageLoadOption interface { + Apply(*imageLoadOpts) error +} +type imageLoadOptionFunc func(opt *imageLoadOpts) error + +func (f imageLoadOptionFunc) Apply(o *imageLoadOpts) error { + return f(o) +} + +type imageLoadOpts struct { + apiOptions image.LoadOptions +} + +// ImageLoadWithQuiet sets the quiet option for the image load operation. +func ImageLoadWithQuiet(quiet bool) ImageLoadOption { + return imageLoadOptionFunc(func(opt *imageLoadOpts) error { + opt.apiOptions.Quiet = quiet + return nil + }) +} + +// ImageLoadWithPlatforms sets the platforms to be loaded from the image. +func ImageLoadWithPlatforms(platforms ...ocispec.Platform) ImageLoadOption { + return imageLoadOptionFunc(func(opt *imageLoadOpts) error { + if opt.apiOptions.Platforms != nil { + return fmt.Errorf("platforms already set to %v", opt.apiOptions.Platforms) + } + opt.apiOptions.Platforms = platforms + return nil + }) +} diff --git a/vendor/github.com/docker/docker/client/image_prune.go b/vendor/github.com/docker/docker/client/image_prune.go index 5ee987e24..7c354d7b1 100644 --- a/vendor/github.com/docker/docker/client/image_prune.go +++ b/vendor/github.com/docker/docker/client/image_prune.go @@ -11,25 +11,24 @@ import ( // ImagesPrune requests the daemon to delete unused data func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (image.PruneReport, error) { - var report image.PruneReport - if err := cli.NewVersionError(ctx, "1.25", "image prune"); err != nil { - return report, err + return image.PruneReport{}, err } query, err := getFiltersQuery(pruneFilters) if err != nil { - return report, err + return image.PruneReport{}, err } - serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/images/prune", query, nil, nil) + defer ensureReaderClosed(resp) if err != nil { - return report, err + return image.PruneReport{}, err } - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, fmt.Errorf("Error retrieving disk usage: %v", err) + var report image.PruneReport + if err := json.NewDecoder(resp.Body).Decode(&report); err != nil { + return image.PruneReport{}, fmt.Errorf("Error retrieving disk usage: %v", err) } return report, nil diff --git a/vendor/github.com/docker/docker/client/image_pull.go b/vendor/github.com/docker/docker/client/image_pull.go index 1634c4c80..4286942b3 100644 --- a/vendor/github.com/docker/docker/client/image_pull.go +++ b/vendor/github.com/docker/docker/client/image_pull.go @@ -45,7 +45,7 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options image.P if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } // getAPITagFromNamedRef returns a tag from the specified reference. diff --git a/vendor/github.com/docker/docker/client/image_push.go b/vendor/github.com/docker/docker/client/image_push.go index 16f9c4651..b340bc4fb 100644 --- a/vendor/github.com/docker/docker/client/image_push.go +++ b/vendor/github.com/docker/docker/client/image_push.go @@ -63,10 +63,10 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options image.Pu if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } -func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) { +func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (*http.Response, error) { return cli.post(ctx, "/images/"+imageID+"/push", query, nil, http.Header{ registry.AuthHeader: {registryAuth}, }) diff --git a/vendor/github.com/docker/docker/client/image_remove.go b/vendor/github.com/docker/docker/client/image_remove.go index 652d1bfa3..b0c87ca09 100644 --- a/vendor/github.com/docker/docker/client/image_remove.go +++ b/vendor/github.com/docker/docker/client/image_remove.go @@ -19,13 +19,13 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options imag query.Set("noprune", "1") } - var dels []image.DeleteResponse resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) defer ensureReaderClosed(resp) if err != nil { - return dels, err + return nil, err } - err = json.NewDecoder(resp.body).Decode(&dels) + var dels []image.DeleteResponse + err = json.NewDecoder(resp.Body).Decode(&dels) return dels, err } diff --git a/vendor/github.com/docker/docker/client/image_save.go b/vendor/github.com/docker/docker/client/image_save.go index d1314e4b2..0aa7177d2 100644 --- a/vendor/github.com/docker/docker/client/image_save.go +++ b/vendor/github.com/docker/docker/client/image_save.go @@ -7,15 +7,35 @@ import ( ) // ImageSave retrieves one or more images from the docker host as an io.ReadCloser. -// It's up to the caller to store the images and close the stream. -func (cli *Client) ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) { +// +// Platforms is an optional parameter that specifies the platforms to save from the image. +// This is only has effect if the input image is a multi-platform image. +func (cli *Client) ImageSave(ctx context.Context, imageIDs []string, saveOpts ...ImageSaveOption) (io.ReadCloser, error) { + var opts imageSaveOpts + for _, opt := range saveOpts { + if err := opt.Apply(&opts); err != nil { + return nil, err + } + } + query := url.Values{ "names": imageIDs, } + if len(opts.apiOptions.Platforms) > 0 { + if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { + return nil, err + } + p, err := encodePlatforms(opts.apiOptions.Platforms...) + if err != nil { + return nil, err + } + query["platform"] = p + } + resp, err := cli.get(ctx, "/images/get", query, nil) if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } diff --git a/vendor/github.com/docker/docker/client/image_save_opts.go b/vendor/github.com/docker/docker/client/image_save_opts.go new file mode 100644 index 000000000..acd8f282b --- /dev/null +++ b/vendor/github.com/docker/docker/client/image_save_opts.go @@ -0,0 +1,33 @@ +package client + +import ( + "fmt" + + "github.com/docker/docker/api/types/image" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +type ImageSaveOption interface { + Apply(*imageSaveOpts) error +} + +type imageSaveOptionFunc func(opt *imageSaveOpts) error + +func (f imageSaveOptionFunc) Apply(o *imageSaveOpts) error { + return f(o) +} + +// ImageSaveWithPlatforms sets the platforms to be saved from the image. +func ImageSaveWithPlatforms(platforms ...ocispec.Platform) ImageSaveOption { + return imageSaveOptionFunc(func(opt *imageSaveOpts) error { + if opt.apiOptions.Platforms != nil { + return fmt.Errorf("platforms already set to %v", opt.apiOptions.Platforms) + } + opt.apiOptions.Platforms = platforms + return nil + }) +} + +type imageSaveOpts struct { + apiOptions image.SaveOptions +} diff --git a/vendor/github.com/docker/docker/client/image_search.go b/vendor/github.com/docker/docker/client/image_search.go index 0a0745757..0a7b5ec22 100644 --- a/vendor/github.com/docker/docker/client/image_search.go +++ b/vendor/github.com/docker/docker/client/image_search.go @@ -43,11 +43,11 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options registr return results, err } - err = json.NewDecoder(resp.body).Decode(&results) + err = json.NewDecoder(resp.Body).Decode(&results) return results, err } -func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { +func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (*http.Response, error) { return cli.get(ctx, "/images/search", query, http.Header{ registry.AuthHeader: {registryAuth}, }) diff --git a/vendor/github.com/docker/docker/client/info.go b/vendor/github.com/docker/docker/client/info.go index cc3fcc467..6396f4b60 100644 --- a/vendor/github.com/docker/docker/client/info.go +++ b/vendor/github.com/docker/docker/client/info.go @@ -12,13 +12,13 @@ import ( // Info returns information about the docker server. func (cli *Client) Info(ctx context.Context) (system.Info, error) { var info system.Info - serverResp, err := cli.get(ctx, "/info", url.Values{}, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/info", url.Values{}, nil) + defer ensureReaderClosed(resp) if err != nil { return info, err } - if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil { + if err := json.NewDecoder(resp.Body).Decode(&info); err != nil { return info, fmt.Errorf("Error reading remote info: %v", err) } diff --git a/vendor/github.com/docker/docker/client/interface_stable.go b/vendor/github.com/docker/docker/client/interface_stable.go deleted file mode 100644 index 5502cd742..000000000 --- a/vendor/github.com/docker/docker/client/interface_stable.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -// APIClient is an interface that clients that talk with a docker server must implement. -type APIClient interface { - CommonAPIClient - apiClientExperimental -} - -// Ensure that Client always implements APIClient. -var _ APIClient = &Client{} diff --git a/vendor/github.com/docker/docker/client/login.go b/vendor/github.com/docker/docker/client/login.go index 19e985e0b..d3572c1bf 100644 --- a/vendor/github.com/docker/docker/client/login.go +++ b/vendor/github.com/docker/docker/client/login.go @@ -19,6 +19,6 @@ func (cli *Client) RegistryLogin(ctx context.Context, auth registry.AuthConfig) } var response registry.AuthenticateOKBody - err = json.NewDecoder(resp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/network_connect.go b/vendor/github.com/docker/docker/client/network_connect.go index 8daf89063..fa7cc34fa 100644 --- a/vendor/github.com/docker/docker/client/network_connect.go +++ b/vendor/github.com/docker/docker/client/network_connect.go @@ -8,6 +8,16 @@ import ( // NetworkConnect connects a container to an existent network in the docker host. func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error { + networkID, err := trimID("network", networkID) + if err != nil { + return err + } + + containerID, err = trimID("container", containerID) + if err != nil { + return err + } + nc := network.ConnectOptions{ Container: containerID, EndpointConfig: config, diff --git a/vendor/github.com/docker/docker/client/network_create.go b/vendor/github.com/docker/docker/client/network_create.go index 850e31cc9..eef951445 100644 --- a/vendor/github.com/docker/docker/client/network_create.go +++ b/vendor/github.com/docker/docker/client/network_create.go @@ -10,15 +10,13 @@ import ( // NetworkCreate creates a new network in the docker host. func (cli *Client) NetworkCreate(ctx context.Context, name string, options network.CreateOptions) (network.CreateResponse, error) { - var response network.CreateResponse - // Make sure we negotiated (if the client is configured to do so), // as code below contains API-version specific handling of options. // // Normally, version-negotiation (if enabled) would not happen until // the API request is made. if err := cli.checkVersion(ctx); err != nil { - return response, err + return network.CreateResponse{}, err } networkCreateRequest := network.CreateRequest{ @@ -30,12 +28,13 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options netwo networkCreateRequest.CheckDuplicate = &enabled //nolint:staticcheck // ignore SA1019: CheckDuplicate is deprecated since API v1.44. } - serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) + defer ensureReaderClosed(resp) if err != nil { - return response, err + return network.CreateResponse{}, err } - err = json.NewDecoder(serverResp.body).Decode(&response) + var response network.CreateResponse + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/network_disconnect.go b/vendor/github.com/docker/docker/client/network_disconnect.go index aaf428d85..d8051df2f 100644 --- a/vendor/github.com/docker/docker/client/network_disconnect.go +++ b/vendor/github.com/docker/docker/client/network_disconnect.go @@ -8,6 +8,16 @@ import ( // NetworkDisconnect disconnects a container from an existent network in the docker host. func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error { + networkID, err := trimID("network", networkID) + if err != nil { + return err + } + + containerID, err = trimID("container", containerID) + if err != nil { + return err + } + nd := network.DisconnectOptions{ Container: containerID, Force: force, diff --git a/vendor/github.com/docker/docker/client/network_inspect.go b/vendor/github.com/docker/docker/client/network_inspect.go index afc47de6f..1387c080a 100644 --- a/vendor/github.com/docker/docker/client/network_inspect.go +++ b/vendor/github.com/docker/docker/client/network_inspect.go @@ -18,8 +18,9 @@ func (cli *Client) NetworkInspect(ctx context.Context, networkID string, options // NetworkInspectWithRaw returns the information for a specific network configured in the docker host and its raw representation. func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, options network.InspectOptions) (network.Inspect, []byte, error) { - if networkID == "" { - return network.Inspect{}, nil, objectNotFoundError{object: "network", id: networkID} + networkID, err := trimID("network", networkID) + if err != nil { + return network.Inspect{}, nil, err } query := url.Values{} if options.Verbose { @@ -35,7 +36,7 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, return network.Inspect{}, nil, err } - raw, err := io.ReadAll(resp.body) + raw, err := io.ReadAll(resp.Body) if err != nil { return network.Inspect{}, nil, err } diff --git a/vendor/github.com/docker/docker/client/network_list.go b/vendor/github.com/docker/docker/client/network_list.go index 72957d47f..e1b4fca73 100644 --- a/vendor/github.com/docker/docker/client/network_list.go +++ b/vendor/github.com/docker/docker/client/network_list.go @@ -27,6 +27,6 @@ func (cli *Client) NetworkList(ctx context.Context, options network.ListOptions) if err != nil { return networkResources, err } - err = json.NewDecoder(resp.body).Decode(&networkResources) + err = json.NewDecoder(resp.Body).Decode(&networkResources) return networkResources, err } diff --git a/vendor/github.com/docker/docker/client/network_prune.go b/vendor/github.com/docker/docker/client/network_prune.go index 708cc61a4..90d3679f3 100644 --- a/vendor/github.com/docker/docker/client/network_prune.go +++ b/vendor/github.com/docker/docker/client/network_prune.go @@ -11,25 +11,24 @@ import ( // NetworksPrune requests the daemon to delete unused networks func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (network.PruneReport, error) { - var report network.PruneReport - if err := cli.NewVersionError(ctx, "1.25", "network prune"); err != nil { - return report, err + return network.PruneReport{}, err } query, err := getFiltersQuery(pruneFilters) if err != nil { - return report, err + return network.PruneReport{}, err } - serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/networks/prune", query, nil, nil) + defer ensureReaderClosed(resp) if err != nil { - return report, err + return network.PruneReport{}, err } - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, fmt.Errorf("Error retrieving network prune report: %v", err) + var report network.PruneReport + if err := json.NewDecoder(resp.Body).Decode(&report); err != nil { + return network.PruneReport{}, fmt.Errorf("Error retrieving network prune report: %v", err) } return report, nil diff --git a/vendor/github.com/docker/docker/client/network_remove.go b/vendor/github.com/docker/docker/client/network_remove.go index 9d6c6cef0..89fdaaf3a 100644 --- a/vendor/github.com/docker/docker/client/network_remove.go +++ b/vendor/github.com/docker/docker/client/network_remove.go @@ -4,6 +4,10 @@ import "context" // NetworkRemove removes an existent network from the docker host. func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { + networkID, err := trimID("network", networkID) + if err != nil { + return err + } resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) defer ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/node_inspect.go b/vendor/github.com/docker/docker/client/node_inspect.go index 95ab9b1be..5d3343dc4 100644 --- a/vendor/github.com/docker/docker/client/node_inspect.go +++ b/vendor/github.com/docker/docker/client/node_inspect.go @@ -11,16 +11,17 @@ import ( // NodeInspectWithRaw returns the node information. func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) { - if nodeID == "" { - return swarm.Node{}, nil, objectNotFoundError{object: "node", id: nodeID} + nodeID, err := trimID("node", nodeID) + if err != nil { + return swarm.Node{}, nil, err } - serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) + defer ensureReaderClosed(resp) if err != nil { return swarm.Node{}, nil, err } - body, err := io.ReadAll(serverResp.body) + body, err := io.ReadAll(resp.Body) if err != nil { return swarm.Node{}, nil, err } diff --git a/vendor/github.com/docker/docker/client/node_list.go b/vendor/github.com/docker/docker/client/node_list.go index 1a9e6bfb1..2534f4aee 100644 --- a/vendor/github.com/docker/docker/client/node_list.go +++ b/vendor/github.com/docker/docker/client/node_list.go @@ -30,6 +30,6 @@ func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions) } var nodes []swarm.Node - err = json.NewDecoder(resp.body).Decode(&nodes) + err = json.NewDecoder(resp.Body).Decode(&nodes) return nodes, err } diff --git a/vendor/github.com/docker/docker/client/node_remove.go b/vendor/github.com/docker/docker/client/node_remove.go index e44436deb..81f8fed6b 100644 --- a/vendor/github.com/docker/docker/client/node_remove.go +++ b/vendor/github.com/docker/docker/client/node_remove.go @@ -9,6 +9,11 @@ import ( // NodeRemove removes a Node. func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error { + nodeID, err := trimID("node", nodeID) + if err != nil { + return err + } + query := url.Values{} if options.Force { query.Set("force", "1") diff --git a/vendor/github.com/docker/docker/client/node_update.go b/vendor/github.com/docker/docker/client/node_update.go index 0d0fc3b78..10e218661 100644 --- a/vendor/github.com/docker/docker/client/node_update.go +++ b/vendor/github.com/docker/docker/client/node_update.go @@ -9,6 +9,11 @@ import ( // NodeUpdate updates a Node. func (cli *Client) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error { + nodeID, err := trimID("node", nodeID) + if err != nil { + return err + } + query := url.Values{} query.Set("version", version.String()) resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, node, nil) diff --git a/vendor/github.com/docker/docker/client/options.go b/vendor/github.com/docker/docker/client/options.go index ddb0ca399..6f68fc2b8 100644 --- a/vendor/github.com/docker/docker/client/options.go +++ b/vendor/github.com/docker/docker/client/options.go @@ -6,11 +6,13 @@ import ( "net/http" "os" "path/filepath" + "strings" "time" "github.com/docker/go-connections/sockets" "github.com/docker/go-connections/tlsconfig" "github.com/pkg/errors" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel/trace" ) @@ -194,8 +196,8 @@ func WithTLSClientConfigFromEnv() Opt { // (see [WithAPIVersionNegotiation]). func WithVersion(version string) Opt { return func(c *Client) error { - if version != "" { - c.version = version + if v := strings.TrimPrefix(version, "v"); v != "" { + c.version = v c.manualOverride = true } return nil @@ -226,8 +228,13 @@ func WithAPIVersionNegotiation() Opt { // WithTraceProvider sets the trace provider for the client. // If this is not set then the global trace provider will be used. func WithTraceProvider(provider trace.TracerProvider) Opt { + return WithTraceOptions(otelhttp.WithTracerProvider(provider)) +} + +// WithTraceOptions sets tracing span options for the client. +func WithTraceOptions(opts ...otelhttp.Option) Opt { return func(c *Client) error { - c.tp = provider + c.traceOpts = append(c.traceOpts, opts...) return nil } } diff --git a/vendor/github.com/docker/docker/client/ping.go b/vendor/github.com/docker/docker/client/ping.go index bf3e9b1cd..c7645e56d 100644 --- a/vendor/github.com/docker/docker/client/ping.go +++ b/vendor/github.com/docker/docker/client/ping.go @@ -8,7 +8,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/errdefs" ) // Ping pings the server and returns the value of the "Docker-Experimental", @@ -28,49 +27,54 @@ func (cli *Client) Ping(ctx context.Context) (types.Ping, error) { if err != nil { return ping, err } - serverResp, err := cli.doRequest(req) - if err == nil { - defer ensureReaderClosed(serverResp) - switch serverResp.statusCode { + resp, err := cli.doRequest(req) + if err != nil { + if IsErrConnectionFailed(err) { + return ping, err + } + // We managed to connect, but got some error; continue and try GET request. + } else { + defer ensureReaderClosed(resp) + switch resp.StatusCode { case http.StatusOK, http.StatusInternalServerError: // Server handled the request, so parse the response - return parsePingResponse(cli, serverResp) + return parsePingResponse(cli, resp) } - } else if IsErrConnectionFailed(err) { - return ping, err } // HEAD failed; fallback to GET. req.Method = http.MethodGet - serverResp, err = cli.doRequest(req) - defer ensureReaderClosed(serverResp) + resp, err = cli.doRequest(req) + defer ensureReaderClosed(resp) if err != nil { return ping, err } - return parsePingResponse(cli, serverResp) + return parsePingResponse(cli, resp) } -func parsePingResponse(cli *Client, resp serverResponse) (types.Ping, error) { +func parsePingResponse(cli *Client, resp *http.Response) (types.Ping, error) { + if resp == nil { + return types.Ping{}, nil + } + var ping types.Ping - if resp.header == nil { - err := cli.checkResponseErr(resp) - return ping, errdefs.FromStatusCode(err, resp.statusCode) + if resp.Header == nil { + return ping, cli.checkResponseErr(resp) } - ping.APIVersion = resp.header.Get("API-Version") - ping.OSType = resp.header.Get("OSType") - if resp.header.Get("Docker-Experimental") == "true" { + ping.APIVersion = resp.Header.Get("Api-Version") + ping.OSType = resp.Header.Get("Ostype") + if resp.Header.Get("Docker-Experimental") == "true" { ping.Experimental = true } - if bv := resp.header.Get("Builder-Version"); bv != "" { + if bv := resp.Header.Get("Builder-Version"); bv != "" { ping.BuilderVersion = types.BuilderVersion(bv) } - if si := resp.header.Get("Swarm"); si != "" { + if si := resp.Header.Get("Swarm"); si != "" { state, role, _ := strings.Cut(si, "/") ping.SwarmStatus = &swarm.Status{ NodeState: swarm.LocalNodeState(state), ControlAvailable: role == "manager", } } - err := cli.checkResponseErr(resp) - return ping, errdefs.FromStatusCode(err, resp.statusCode) + return ping, cli.checkResponseErr(resp) } diff --git a/vendor/github.com/docker/docker/client/plugin_disable.go b/vendor/github.com/docker/docker/client/plugin_disable.go index 01f6574f9..9fabe77bf 100644 --- a/vendor/github.com/docker/docker/client/plugin_disable.go +++ b/vendor/github.com/docker/docker/client/plugin_disable.go @@ -9,6 +9,10 @@ import ( // PluginDisable disables a plugin func (cli *Client) PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error { + name, err := trimID("plugin", name) + if err != nil { + return err + } query := url.Values{} if options.Force { query.Set("force", "1") diff --git a/vendor/github.com/docker/docker/client/plugin_enable.go b/vendor/github.com/docker/docker/client/plugin_enable.go index 736da48bd..492d0bcff 100644 --- a/vendor/github.com/docker/docker/client/plugin_enable.go +++ b/vendor/github.com/docker/docker/client/plugin_enable.go @@ -10,6 +10,10 @@ import ( // PluginEnable enables a plugin func (cli *Client) PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error { + name, err := trimID("plugin", name) + if err != nil { + return err + } query := url.Values{} query.Set("timeout", strconv.Itoa(options.Timeout)) diff --git a/vendor/github.com/docker/docker/client/plugin_inspect.go b/vendor/github.com/docker/docker/client/plugin_inspect.go index f09e46066..8f107a760 100644 --- a/vendor/github.com/docker/docker/client/plugin_inspect.go +++ b/vendor/github.com/docker/docker/client/plugin_inspect.go @@ -11,8 +11,9 @@ import ( // PluginInspectWithRaw inspects an existing plugin func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) { - if name == "" { - return nil, nil, objectNotFoundError{object: "plugin", id: name} + name, err := trimID("plugin", name) + if err != nil { + return nil, nil, err } resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) defer ensureReaderClosed(resp) @@ -20,7 +21,7 @@ func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*type return nil, nil, err } - body, err := io.ReadAll(resp.body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, nil, err } diff --git a/vendor/github.com/docker/docker/client/plugin_install.go b/vendor/github.com/docker/docker/client/plugin_install.go index a0d8c3500..b04dcf9a1 100644 --- a/vendor/github.com/docker/docker/client/plugin_install.go +++ b/vendor/github.com/docker/docker/client/plugin_install.go @@ -35,13 +35,13 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types return nil, err } - name = resp.header.Get("Docker-Plugin-Name") + name = resp.Header.Get("Docker-Plugin-Name") pr, pw := io.Pipe() go func() { // todo: the client should probably be designed more around the actual api - _, err := io.Copy(pw, resp.body) + _, err := io.Copy(pw, resp.Body) if err != nil { - pw.CloseWithError(err) + _ = pw.CloseWithError(err) return } defer func() { @@ -52,29 +52,29 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types }() if len(options.Args) > 0 { if err := cli.PluginSet(ctx, name, options.Args); err != nil { - pw.CloseWithError(err) + _ = pw.CloseWithError(err) return } } if options.Disabled { - pw.Close() + _ = pw.Close() return } enableErr := cli.PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: 0}) - pw.CloseWithError(enableErr) + _ = pw.CloseWithError(enableErr) }() return pr, nil } -func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { +func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (*http.Response, error) { return cli.get(ctx, "/plugins/privileges", query, http.Header{ registry.AuthHeader: {registryAuth}, }) } -func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges types.PluginPrivileges, registryAuth string) (serverResponse, error) { +func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges types.PluginPrivileges, registryAuth string) (*http.Response, error) { return cli.post(ctx, "/plugins/pull", query, privileges, http.Header{ registry.AuthHeader: {registryAuth}, }) @@ -98,7 +98,7 @@ func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, } var privileges types.PluginPrivileges - if err := json.NewDecoder(resp.body).Decode(&privileges); err != nil { + if err := json.NewDecoder(resp.Body).Decode(&privileges); err != nil { ensureReaderClosed(resp) return nil, err } diff --git a/vendor/github.com/docker/docker/client/plugin_list.go b/vendor/github.com/docker/docker/client/plugin_list.go index 2091a054d..03bcf7621 100644 --- a/vendor/github.com/docker/docker/client/plugin_list.go +++ b/vendor/github.com/docker/docker/client/plugin_list.go @@ -28,6 +28,6 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P return plugins, err } - err = json.NewDecoder(resp.body).Decode(&plugins) + err = json.NewDecoder(resp.Body).Decode(&plugins) return plugins, err } diff --git a/vendor/github.com/docker/docker/client/plugin_push.go b/vendor/github.com/docker/docker/client/plugin_push.go index 8f68a86ee..da15e449d 100644 --- a/vendor/github.com/docker/docker/client/plugin_push.go +++ b/vendor/github.com/docker/docker/client/plugin_push.go @@ -10,11 +10,15 @@ import ( // PluginPush pushes a plugin to a registry func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) { + name, err := trimID("plugin", name) + if err != nil { + return nil, err + } resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, http.Header{ registry.AuthHeader: {registryAuth}, }) if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } diff --git a/vendor/github.com/docker/docker/client/plugin_remove.go b/vendor/github.com/docker/docker/client/plugin_remove.go index 4cd66958c..6ee107e3c 100644 --- a/vendor/github.com/docker/docker/client/plugin_remove.go +++ b/vendor/github.com/docker/docker/client/plugin_remove.go @@ -9,6 +9,11 @@ import ( // PluginRemove removes a plugin func (cli *Client) PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error { + name, err := trimID("plugin", name) + if err != nil { + return err + } + query := url.Values{} if options.Force { query.Set("force", "1") diff --git a/vendor/github.com/docker/docker/client/plugin_set.go b/vendor/github.com/docker/docker/client/plugin_set.go index dcf5752ca..e2a79838d 100644 --- a/vendor/github.com/docker/docker/client/plugin_set.go +++ b/vendor/github.com/docker/docker/client/plugin_set.go @@ -6,6 +6,11 @@ import ( // PluginSet modifies settings for an existing plugin func (cli *Client) PluginSet(ctx context.Context, name string, args []string) error { + name, err := trimID("plugin", name) + if err != nil { + return err + } + resp, err := cli.post(ctx, "/plugins/"+name+"/set", nil, args, nil) ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/plugin_upgrade.go b/vendor/github.com/docker/docker/client/plugin_upgrade.go index 5cade450f..4abb29cf0 100644 --- a/vendor/github.com/docker/docker/client/plugin_upgrade.go +++ b/vendor/github.com/docker/docker/client/plugin_upgrade.go @@ -13,7 +13,12 @@ import ( ) // PluginUpgrade upgrades a plugin -func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) { +func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error) { + name, err := trimID("plugin", name) + if err != nil { + return nil, err + } + if err := cli.NewVersionError(ctx, "1.26", "plugin upgrade"); err != nil { return nil, err } @@ -32,10 +37,10 @@ func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } -func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges types.PluginPrivileges, name, registryAuth string) (serverResponse, error) { +func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges types.PluginPrivileges, name, registryAuth string) (*http.Response, error) { return cli.post(ctx, "/plugins/"+name+"/upgrade", query, privileges, http.Header{ registry.AuthHeader: {registryAuth}, }) diff --git a/vendor/github.com/docker/docker/client/request.go b/vendor/github.com/docker/docker/client/request.go index 6eea9b4e4..2b913aab6 100644 --- a/vendor/github.com/docker/docker/client/request.go +++ b/vendor/github.com/docker/docker/client/request.go @@ -19,47 +19,39 @@ import ( "github.com/pkg/errors" ) -// serverResponse is a wrapper for http API responses. -type serverResponse struct { - body io.ReadCloser - header http.Header - statusCode int - reqURL *url.URL -} - // head sends an http request to the docker API using the method HEAD. -func (cli *Client) head(ctx context.Context, path string, query url.Values, headers http.Header) (serverResponse, error) { +func (cli *Client) head(ctx context.Context, path string, query url.Values, headers http.Header) (*http.Response, error) { return cli.sendRequest(ctx, http.MethodHead, path, query, nil, headers) } // get sends an http request to the docker API using the method GET with a specific Go context. -func (cli *Client) get(ctx context.Context, path string, query url.Values, headers http.Header) (serverResponse, error) { +func (cli *Client) get(ctx context.Context, path string, query url.Values, headers http.Header) (*http.Response, error) { return cli.sendRequest(ctx, http.MethodGet, path, query, nil, headers) } // post sends an http request to the docker API using the method POST with a specific Go context. -func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers http.Header) (serverResponse, error) { +func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers http.Header) (*http.Response, error) { body, headers, err := encodeBody(obj, headers) if err != nil { - return serverResponse{}, err + return nil, err } return cli.sendRequest(ctx, http.MethodPost, path, query, body, headers) } -func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers http.Header) (serverResponse, error) { +func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers http.Header) (*http.Response, error) { return cli.sendRequest(ctx, http.MethodPost, path, query, body, headers) } -func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers http.Header) (serverResponse, error) { +func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers http.Header) (*http.Response, error) { body, headers, err := encodeBody(obj, headers) if err != nil { - return serverResponse{}, err + return nil, err } return cli.putRaw(ctx, path, query, body, headers) } // putRaw sends an http request to the docker API using the method PUT. -func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers http.Header) (serverResponse, error) { +func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers http.Header) (*http.Response, error) { // PUT requests are expected to always have a body (apparently) // so explicitly pass an empty body to sendRequest to signal that // it should set the Content-Type header if not already present. @@ -70,7 +62,7 @@ func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, bo } // delete sends an http request to the docker API using the method DELETE. -func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers http.Header) (serverResponse, error) { +func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers http.Header) (*http.Response, error) { return cli.sendRequest(ctx, http.MethodDelete, path, query, nil, headers) } @@ -116,59 +108,60 @@ func (cli *Client) buildRequest(ctx context.Context, method, path string, body i return req, nil } -func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers http.Header) (serverResponse, error) { +func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers http.Header) (*http.Response, error) { req, err := cli.buildRequest(ctx, method, cli.getAPIPath(ctx, path, query), body, headers) if err != nil { - return serverResponse{}, err + return nil, err } resp, err := cli.doRequest(req) switch { case errors.Is(err, context.Canceled): - return serverResponse{}, errdefs.Cancelled(err) + return nil, errdefs.Cancelled(err) case errors.Is(err, context.DeadlineExceeded): - return serverResponse{}, errdefs.Deadline(err) + return nil, errdefs.Deadline(err) case err == nil: - err = cli.checkResponseErr(resp) + return resp, cli.checkResponseErr(resp) + default: + return resp, err } - return resp, errdefs.FromStatusCode(err, resp.statusCode) } -// FIXME(thaJeztah): Should this actually return a serverResp when a connection error occurred? -func (cli *Client) doRequest(req *http.Request) (serverResponse, error) { - serverResp := serverResponse{statusCode: -1, reqURL: req.URL} - +func (cli *Client) doRequest(req *http.Request) (*http.Response, error) { resp, err := cli.client.Do(req) if err != nil { if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") { - return serverResp, errConnectionFailed{fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)} + return nil, errConnectionFailed{fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)} } if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") { - return serverResp, errConnectionFailed{errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")} + return nil, errConnectionFailed{errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")} } // Don't decorate context sentinel errors; users may be comparing to // them directly. if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { - return serverResp, err + return nil, err } - if uErr, ok := err.(*url.Error); ok { - if nErr, ok := uErr.Err.(*net.OpError); ok { + var uErr *url.Error + if errors.As(err, &uErr) { + var nErr *net.OpError + if errors.As(uErr.Err, &nErr) { if os.IsPermission(nErr.Err) { - return serverResp, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)} + return nil, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)} } } } - if nErr, ok := err.(net.Error); ok { + var nErr net.Error + if errors.As(err, &nErr) { // FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)? if nErr.Timeout() { - return serverResp, ErrorConnectionFailed(cli.host) + return nil, connectionFailed(cli.host) } if strings.Contains(nErr.Error(), "connection refused") || strings.Contains(nErr.Error(), "dial unix") { - return serverResp, ErrorConnectionFailed(cli.host) + return nil, connectionFailed(cli.host) } } @@ -192,28 +185,37 @@ func (cli *Client) doRequest(req *http.Request) (serverResponse, error) { } } - return serverResp, errConnectionFailed{errors.Wrap(err, "error during connect")} + return nil, errConnectionFailed{errors.Wrap(err, "error during connect")} } - if resp != nil { - serverResp.statusCode = resp.StatusCode - serverResp.body = resp.Body - serverResp.header = resp.Header - } - return serverResp, nil + return resp, nil } -func (cli *Client) checkResponseErr(serverResp serverResponse) error { - if serverResp.statusCode >= 200 && serverResp.statusCode < 400 { +func (cli *Client) checkResponseErr(serverResp *http.Response) (retErr error) { + if serverResp == nil { return nil } + if serverResp.StatusCode >= 200 && serverResp.StatusCode < 400 { + return nil + } + defer func() { + retErr = errdefs.FromStatusCode(retErr, serverResp.StatusCode) + }() var body []byte var err error - if serverResp.body != nil { + var reqURL string + if serverResp.Request != nil { + reqURL = serverResp.Request.URL.String() + } + statusMsg := serverResp.Status + if statusMsg == "" { + statusMsg = http.StatusText(serverResp.StatusCode) + } + if serverResp.Body != nil { bodyMax := 1 * 1024 * 1024 // 1 MiB bodyR := &io.LimitedReader{ - R: serverResp.body, + R: serverResp.Body, N: int64(bodyMax), } body, err = io.ReadAll(bodyR) @@ -221,21 +223,54 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error { return err } if bodyR.N == 0 { - return fmt.Errorf("request returned %s with a message (> %d bytes) for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), bodyMax, serverResp.reqURL) + if reqURL != "" { + return fmt.Errorf("request returned %s with a message (> %d bytes) for API route and version %s, check if the server supports the requested API version", statusMsg, bodyMax, reqURL) + } + return fmt.Errorf("request returned %s with a message (> %d bytes); check if the server supports the requested API version", statusMsg, bodyMax) } } if len(body) == 0 { - return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), serverResp.reqURL) + if reqURL != "" { + return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", statusMsg, reqURL) + } + return fmt.Errorf("request returned %s; check if the server supports the requested API version", statusMsg) } var daemonErr error - if serverResp.header.Get("Content-Type") == "application/json" && (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) { + if serverResp.Header.Get("Content-Type") == "application/json" && (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) { var errorResponse types.ErrorResponse if err := json.Unmarshal(body, &errorResponse); err != nil { return errors.Wrap(err, "Error reading JSON") } - daemonErr = errors.New(strings.TrimSpace(errorResponse.Message)) + if errorResponse.Message == "" { + // Error-message is empty, which means that we successfully parsed the + // JSON-response (no error produced), but it didn't contain an error + // message. This could either be because the response was empty, or + // the response was valid JSON, but not with the expected schema + // ([types.ErrorResponse]). + // + // We cannot use "strict" JSON handling (json.NewDecoder with DisallowUnknownFields) + // due to the API using an open schema (we must anticipate fields + // being added to [types.ErrorResponse] in the future, and not + // reject those responses. + // + // For these cases, we construct an error with the status-code + // returned, but we could consider returning (a truncated version + // of) the actual response as-is. + // + // TODO(thaJeztah): consider adding a log.Debug to allow clients to debug the actual response when enabling debug logging. + daemonErr = fmt.Errorf(`API returned a %d (%s) but provided no error-message`, + serverResp.StatusCode, + http.StatusText(serverResp.StatusCode), + ) + } else { + daemonErr = errors.New(strings.TrimSpace(errorResponse.Message)) + } } else { + // Fall back to returning the response as-is for API versions < 1.24 + // that didn't support JSON error responses, and for situations + // where a plain text error is returned. This branch may also catch + // situations where a proxy is involved, returning a HTML response. daemonErr = errors.New(strings.TrimSpace(string(body))) } return errors.Wrap(daemonErr, "Error response from daemon") @@ -275,10 +310,16 @@ func encodeData(data interface{}) (*bytes.Buffer, error) { return params, nil } -func ensureReaderClosed(response serverResponse) { - if response.body != nil { +func ensureReaderClosed(response *http.Response) { + if response != nil && response.Body != nil { // Drain up to 512 bytes and close the body to let the Transport reuse the connection - _, _ = io.CopyN(io.Discard, response.body, 512) - _ = response.body.Close() + // see https://github.com/google/go-github/pull/317/files#r57536827 + // + // TODO(thaJeztah): see if this optimization is still needed, or already implemented in stdlib, + // and check if context-cancellation should handle this as well. If still needed, consider + // wrapping response.Body, or returning a "closer()" from [Client.sendRequest] and related + // methods. + _, _ = io.CopyN(io.Discard, response.Body, 512) + _ = response.Body.Close() } } diff --git a/vendor/github.com/docker/docker/client/secret_create.go b/vendor/github.com/docker/docker/client/secret_create.go index 7b7f1ba74..bbd119187 100644 --- a/vendor/github.com/docker/docker/client/secret_create.go +++ b/vendor/github.com/docker/docker/client/secret_create.go @@ -10,16 +10,16 @@ import ( // SecretCreate creates a new secret. func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) { - var response types.SecretCreateResponse if err := cli.NewVersionError(ctx, "1.25", "secret create"); err != nil { - return response, err + return types.SecretCreateResponse{}, err } resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil) defer ensureReaderClosed(resp) if err != nil { - return response, err + return types.SecretCreateResponse{}, err } - err = json.NewDecoder(resp.body).Decode(&response) + var response types.SecretCreateResponse + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/secret_inspect.go b/vendor/github.com/docker/docker/client/secret_inspect.go index a9cb59889..fdabc197f 100644 --- a/vendor/github.com/docker/docker/client/secret_inspect.go +++ b/vendor/github.com/docker/docker/client/secret_inspect.go @@ -11,11 +11,12 @@ import ( // SecretInspectWithRaw returns the secret information with raw data func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) { - if err := cli.NewVersionError(ctx, "1.25", "secret inspect"); err != nil { + id, err := trimID("secret", id) + if err != nil { return swarm.Secret{}, nil, err } - if id == "" { - return swarm.Secret{}, nil, objectNotFoundError{object: "secret", id: id} + if err := cli.NewVersionError(ctx, "1.25", "secret inspect"); err != nil { + return swarm.Secret{}, nil, err } resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) defer ensureReaderClosed(resp) @@ -23,7 +24,7 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S return swarm.Secret{}, nil, err } - body, err := io.ReadAll(resp.body) + body, err := io.ReadAll(resp.Body) if err != nil { return swarm.Secret{}, nil, err } diff --git a/vendor/github.com/docker/docker/client/secret_list.go b/vendor/github.com/docker/docker/client/secret_list.go index 4d21639ef..e3b7dbdb9 100644 --- a/vendor/github.com/docker/docker/client/secret_list.go +++ b/vendor/github.com/docker/docker/client/secret_list.go @@ -33,6 +33,6 @@ func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptio } var secrets []swarm.Secret - err = json.NewDecoder(resp.body).Decode(&secrets) + err = json.NewDecoder(resp.Body).Decode(&secrets) return secrets, err } diff --git a/vendor/github.com/docker/docker/client/secret_remove.go b/vendor/github.com/docker/docker/client/secret_remove.go index 079ed6739..7ea2acbf5 100644 --- a/vendor/github.com/docker/docker/client/secret_remove.go +++ b/vendor/github.com/docker/docker/client/secret_remove.go @@ -4,6 +4,10 @@ import "context" // SecretRemove removes a secret. func (cli *Client) SecretRemove(ctx context.Context, id string) error { + id, err := trimID("secret", id) + if err != nil { + return err + } if err := cli.NewVersionError(ctx, "1.25", "secret remove"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/client/secret_update.go b/vendor/github.com/docker/docker/client/secret_update.go index 9dfe67198..60d21a6f2 100644 --- a/vendor/github.com/docker/docker/client/secret_update.go +++ b/vendor/github.com/docker/docker/client/secret_update.go @@ -9,6 +9,10 @@ import ( // SecretUpdate attempts to update a secret. func (cli *Client) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error { + id, err := trimID("secret", id) + if err != nil { + return err + } if err := cli.NewVersionError(ctx, "1.25", "secret update"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/client/service_create.go b/vendor/github.com/docker/docker/client/service_create.go index b72cb420d..fb12dd5b5 100644 --- a/vendor/github.com/docker/docker/client/service_create.go +++ b/vendor/github.com/docker/docker/client/service_create.go @@ -73,7 +73,7 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, return response, err } - err = json.NewDecoder(resp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) if resolveWarning != "" { response.Warnings = append(response.Warnings, resolveWarning) } diff --git a/vendor/github.com/docker/docker/client/service_inspect.go b/vendor/github.com/docker/docker/client/service_inspect.go index cee020c98..77b4402d3 100644 --- a/vendor/github.com/docker/docker/client/service_inspect.go +++ b/vendor/github.com/docker/docker/client/service_inspect.go @@ -14,18 +14,20 @@ import ( // ServiceInspectWithRaw returns the service information and the raw data. func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error) { - if serviceID == "" { - return swarm.Service{}, nil, objectNotFoundError{object: "service", id: serviceID} + serviceID, err := trimID("service", serviceID) + if err != nil { + return swarm.Service{}, nil, err } + query := url.Values{} query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults)) - serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/services/"+serviceID, query, nil) + defer ensureReaderClosed(resp) if err != nil { return swarm.Service{}, nil, err } - body, err := io.ReadAll(serverResp.body) + body, err := io.ReadAll(resp.Body) if err != nil { return swarm.Service{}, nil, err } diff --git a/vendor/github.com/docker/docker/client/service_list.go b/vendor/github.com/docker/docker/client/service_list.go index f97ec75a5..f589a8423 100644 --- a/vendor/github.com/docker/docker/client/service_list.go +++ b/vendor/github.com/docker/docker/client/service_list.go @@ -34,6 +34,6 @@ func (cli *Client) ServiceList(ctx context.Context, options types.ServiceListOpt } var services []swarm.Service - err = json.NewDecoder(resp.body).Decode(&services) + err = json.NewDecoder(resp.Body).Decode(&services) return services, err } diff --git a/vendor/github.com/docker/docker/client/service_logs.go b/vendor/github.com/docker/docker/client/service_logs.go index e9e30a2ab..6e0cbee49 100644 --- a/vendor/github.com/docker/docker/client/service_logs.go +++ b/vendor/github.com/docker/docker/client/service_logs.go @@ -14,6 +14,11 @@ import ( // ServiceLogs returns the logs generated by a service in an io.ReadCloser. // It's up to the caller to close the stream. func (cli *Client) ServiceLogs(ctx context.Context, serviceID string, options container.LogsOptions) (io.ReadCloser, error) { + serviceID, err := trimID("service", serviceID) + if err != nil { + return nil, err + } + query := url.Values{} if options.ShowStdout { query.Set("stdout", "1") @@ -48,5 +53,5 @@ func (cli *Client) ServiceLogs(ctx context.Context, serviceID string, options co if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } diff --git a/vendor/github.com/docker/docker/client/service_remove.go b/vendor/github.com/docker/docker/client/service_remove.go index 2c46326eb..93c949e44 100644 --- a/vendor/github.com/docker/docker/client/service_remove.go +++ b/vendor/github.com/docker/docker/client/service_remove.go @@ -4,6 +4,11 @@ import "context" // ServiceRemove kills and removes a service. func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error { + serviceID, err := trimID("service", serviceID) + if err != nil { + return err + } + resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) defer ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/service_update.go b/vendor/github.com/docker/docker/client/service_update.go index d2f03f02f..ecb98f468 100644 --- a/vendor/github.com/docker/docker/client/service_update.go +++ b/vendor/github.com/docker/docker/client/service_update.go @@ -16,7 +16,10 @@ import ( // It should be the value as set *before* the update. You can find this value in the Meta field // of swarm.Service, which can be found using ServiceInspectWithRaw. func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) { - response := swarm.ServiceUpdateResponse{} + serviceID, err := trimID("service", serviceID) + if err != nil { + return swarm.ServiceUpdateResponse{}, err + } // Make sure we negotiated (if the client is configured to do so), // as code below contains API-version specific handling of options. @@ -24,7 +27,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version // Normally, version-negotiation (if enabled) would not happen until // the API request is made. if err := cli.checkVersion(ctx); err != nil { - return response, err + return swarm.ServiceUpdateResponse{}, err } query := url.Values{} @@ -39,7 +42,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version query.Set("version", version.String()) if err := validateServiceSpec(service); err != nil { - return response, err + return swarm.ServiceUpdateResponse{}, err } // ensure that the image is tagged @@ -74,10 +77,11 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) defer ensureReaderClosed(resp) if err != nil { - return response, err + return swarm.ServiceUpdateResponse{}, err } - err = json.NewDecoder(resp.body).Decode(&response) + var response swarm.ServiceUpdateResponse + err = json.NewDecoder(resp.Body).Decode(&response) if resolveWarning != "" { response.Warnings = append(response.Warnings, resolveWarning) } diff --git a/vendor/github.com/docker/docker/client/swarm_get_unlock_key.go b/vendor/github.com/docker/docker/client/swarm_get_unlock_key.go index 19f59dd58..271fc08c9 100644 --- a/vendor/github.com/docker/docker/client/swarm_get_unlock_key.go +++ b/vendor/github.com/docker/docker/client/swarm_get_unlock_key.go @@ -9,13 +9,13 @@ import ( // SwarmGetUnlockKey retrieves the swarm's unlock key. func (cli *Client) SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) { - serverResp, err := cli.get(ctx, "/swarm/unlockkey", nil, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/swarm/unlockkey", nil, nil) + defer ensureReaderClosed(resp) if err != nil { return types.SwarmUnlockKeyResponse{}, err } var response types.SwarmUnlockKeyResponse - err = json.NewDecoder(serverResp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/swarm_init.go b/vendor/github.com/docker/docker/client/swarm_init.go index da3c1637e..3dcb2a5b5 100644 --- a/vendor/github.com/docker/docker/client/swarm_init.go +++ b/vendor/github.com/docker/docker/client/swarm_init.go @@ -9,13 +9,13 @@ import ( // SwarmInit initializes the swarm. func (cli *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { - serverResp, err := cli.post(ctx, "/swarm/init", nil, req, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/swarm/init", nil, req, nil) + defer ensureReaderClosed(resp) if err != nil { return "", err } var response string - err = json.NewDecoder(serverResp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/swarm_inspect.go b/vendor/github.com/docker/docker/client/swarm_inspect.go index b52b67a88..3d5a8a042 100644 --- a/vendor/github.com/docker/docker/client/swarm_inspect.go +++ b/vendor/github.com/docker/docker/client/swarm_inspect.go @@ -9,13 +9,13 @@ import ( // SwarmInspect inspects the swarm. func (cli *Client) SwarmInspect(ctx context.Context) (swarm.Swarm, error) { - serverResp, err := cli.get(ctx, "/swarm", nil, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.get(ctx, "/swarm", nil, nil) + defer ensureReaderClosed(resp) if err != nil { return swarm.Swarm{}, err } var response swarm.Swarm - err = json.NewDecoder(serverResp.body).Decode(&response) + err = json.NewDecoder(resp.Body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/swarm_unlock.go b/vendor/github.com/docker/docker/client/swarm_unlock.go index d2412f7d4..745d64d5b 100644 --- a/vendor/github.com/docker/docker/client/swarm_unlock.go +++ b/vendor/github.com/docker/docker/client/swarm_unlock.go @@ -8,7 +8,7 @@ import ( // SwarmUnlock unlocks locked swarm. func (cli *Client) SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error { - serverResp, err := cli.post(ctx, "/swarm/unlock", nil, req, nil) - ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/swarm/unlock", nil, req, nil) + ensureReaderClosed(resp) return err } diff --git a/vendor/github.com/docker/docker/client/task_inspect.go b/vendor/github.com/docker/docker/client/task_inspect.go index dde1f6c59..37668bd27 100644 --- a/vendor/github.com/docker/docker/client/task_inspect.go +++ b/vendor/github.com/docker/docker/client/task_inspect.go @@ -11,16 +11,18 @@ import ( // TaskInspectWithRaw returns the task information and its raw representation. func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) { - if taskID == "" { - return swarm.Task{}, nil, objectNotFoundError{object: "task", id: taskID} + taskID, err := trimID("task", taskID) + if err != nil { + return swarm.Task{}, nil, err } - serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) - defer ensureReaderClosed(serverResp) + + resp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) + defer ensureReaderClosed(resp) if err != nil { return swarm.Task{}, nil, err } - body, err := io.ReadAll(serverResp.body) + body, err := io.ReadAll(resp.Body) if err != nil { return swarm.Task{}, nil, err } diff --git a/vendor/github.com/docker/docker/client/task_list.go b/vendor/github.com/docker/docker/client/task_list.go index 4869b4449..aba7f61e6 100644 --- a/vendor/github.com/docker/docker/client/task_list.go +++ b/vendor/github.com/docker/docker/client/task_list.go @@ -30,6 +30,6 @@ func (cli *Client) TaskList(ctx context.Context, options types.TaskListOptions) } var tasks []swarm.Task - err = json.NewDecoder(resp.body).Decode(&tasks) + err = json.NewDecoder(resp.Body).Decode(&tasks) return tasks, err } diff --git a/vendor/github.com/docker/docker/client/task_logs.go b/vendor/github.com/docker/docker/client/task_logs.go index b8c20e71d..9dcb977b3 100644 --- a/vendor/github.com/docker/docker/client/task_logs.go +++ b/vendor/github.com/docker/docker/client/task_logs.go @@ -47,5 +47,5 @@ func (cli *Client) TaskLogs(ctx context.Context, taskID string, options containe if err != nil { return nil, err } - return resp.body, nil + return resp.Body, nil } diff --git a/vendor/github.com/docker/docker/client/utils.go b/vendor/github.com/docker/docker/client/utils.go index 7f3ff44eb..925d4d8d3 100644 --- a/vendor/github.com/docker/docker/client/utils.go +++ b/vendor/github.com/docker/docker/client/utils.go @@ -1,13 +1,35 @@ package client // import "github.com/docker/docker/client" import ( + "encoding/json" + "fmt" "net/url" - "regexp" + "strings" "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/errdefs" + "github.com/docker/docker/internal/lazyregexp" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) -var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`) +var headerRegexp = lazyregexp.New(`\ADocker/.+\s\((.+)\)\z`) + +type emptyIDError string + +func (e emptyIDError) InvalidParameter() {} + +func (e emptyIDError) Error() string { + return "invalid " + string(e) + " name or ID: value is empty" +} + +// trimID trims the given object-ID / name, returning an error if it's empty. +func trimID(objType, id string) (string, error) { + id = strings.TrimSpace(id) + if len(id) == 0 { + return "", emptyIDError(objType) + } + return id, nil +} // getDockerOS returns the operating system based on the server header from the daemon. func getDockerOS(serverHeader string) string { @@ -32,3 +54,43 @@ func getFiltersQuery(f filters.Args) (url.Values, error) { } return query, nil } + +// encodePlatforms marshals the given platform(s) to JSON format, to +// be used for query-parameters for filtering / selecting platforms. +func encodePlatforms(platform ...ocispec.Platform) ([]string, error) { + if len(platform) == 0 { + return []string{}, nil + } + if len(platform) == 1 { + p, err := encodePlatform(&platform[0]) + if err != nil { + return nil, err + } + return []string{p}, nil + } + + seen := make(map[string]struct{}, len(platform)) + out := make([]string, 0, len(platform)) + for i := range platform { + p, err := encodePlatform(&platform[i]) + if err != nil { + return nil, err + } + if _, ok := seen[p]; !ok { + out = append(out, p) + seen[p] = struct{}{} + } + } + return out, nil +} + +// encodePlatform marshals the given platform to JSON format, to +// be used for query-parameters for filtering / selecting platforms. It +// is used as a helper for encodePlatforms, +func encodePlatform(platform *ocispec.Platform) (string, error) { + p, err := json.Marshal(platform) + if err != nil { + return "", errdefs.InvalidParameter(fmt.Errorf("invalid platform: %v", err)) + } + return string(p), nil +} diff --git a/vendor/github.com/docker/docker/client/version.go b/vendor/github.com/docker/docker/client/version.go index 8f17ff4e8..4566fd98e 100644 --- a/vendor/github.com/docker/docker/client/version.go +++ b/vendor/github.com/docker/docker/client/version.go @@ -16,6 +16,6 @@ func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) { } var server types.Version - err = json.NewDecoder(resp.body).Decode(&server) + err = json.NewDecoder(resp.Body).Decode(&server) return server, err } diff --git a/vendor/github.com/docker/docker/client/volume_create.go b/vendor/github.com/docker/docker/client/volume_create.go index b3b182437..bedb3abbb 100644 --- a/vendor/github.com/docker/docker/client/volume_create.go +++ b/vendor/github.com/docker/docker/client/volume_create.go @@ -9,12 +9,13 @@ import ( // VolumeCreate creates a volume in the docker host. func (cli *Client) VolumeCreate(ctx context.Context, options volume.CreateOptions) (volume.Volume, error) { - var vol volume.Volume resp, err := cli.post(ctx, "/volumes/create", nil, options, nil) defer ensureReaderClosed(resp) if err != nil { - return vol, err + return volume.Volume{}, err } - err = json.NewDecoder(resp.body).Decode(&vol) + + var vol volume.Volume + err = json.NewDecoder(resp.Body).Decode(&vol) return vol, err } diff --git a/vendor/github.com/docker/docker/client/volume_inspect.go b/vendor/github.com/docker/docker/client/volume_inspect.go index b3ba4e604..ce32bbbb7 100644 --- a/vendor/github.com/docker/docker/client/volume_inspect.go +++ b/vendor/github.com/docker/docker/client/volume_inspect.go @@ -17,21 +17,23 @@ func (cli *Client) VolumeInspect(ctx context.Context, volumeID string) (volume.V // VolumeInspectWithRaw returns the information about a specific volume in the docker host and its raw representation func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (volume.Volume, []byte, error) { - if volumeID == "" { - return volume.Volume{}, nil, objectNotFoundError{object: "volume", id: volumeID} + volumeID, err := trimID("volume", volumeID) + if err != nil { + return volume.Volume{}, nil, err } - var vol volume.Volume resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil) defer ensureReaderClosed(resp) if err != nil { - return vol, nil, err + return volume.Volume{}, nil, err } - body, err := io.ReadAll(resp.body) + body, err := io.ReadAll(resp.Body) if err != nil { - return vol, nil, err + return volume.Volume{}, nil, err } + + var vol volume.Volume rdr := bytes.NewReader(body) err = json.NewDecoder(rdr).Decode(&vol) return vol, body, err diff --git a/vendor/github.com/docker/docker/client/volume_list.go b/vendor/github.com/docker/docker/client/volume_list.go index d5ea9827c..de6ce23a4 100644 --- a/vendor/github.com/docker/docker/client/volume_list.go +++ b/vendor/github.com/docker/docker/client/volume_list.go @@ -11,23 +11,23 @@ import ( // VolumeList returns the volumes configured in the docker host. func (cli *Client) VolumeList(ctx context.Context, options volume.ListOptions) (volume.ListResponse, error) { - var volumes volume.ListResponse query := url.Values{} if options.Filters.Len() > 0 { //nolint:staticcheck // ignore SA1019 for old code filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters) if err != nil { - return volumes, err + return volume.ListResponse{}, err } query.Set("filters", filterJSON) } resp, err := cli.get(ctx, "/volumes", query, nil) defer ensureReaderClosed(resp) if err != nil { - return volumes, err + return volume.ListResponse{}, err } - err = json.NewDecoder(resp.body).Decode(&volumes) + var volumes volume.ListResponse + err = json.NewDecoder(resp.Body).Decode(&volumes) return volumes, err } diff --git a/vendor/github.com/docker/docker/client/volume_prune.go b/vendor/github.com/docker/docker/client/volume_prune.go index 9b09c30fa..7da148fea 100644 --- a/vendor/github.com/docker/docker/client/volume_prune.go +++ b/vendor/github.com/docker/docker/client/volume_prune.go @@ -11,25 +11,24 @@ import ( // VolumesPrune requests the daemon to delete unused data func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (volume.PruneReport, error) { - var report volume.PruneReport - if err := cli.NewVersionError(ctx, "1.25", "volume prune"); err != nil { - return report, err + return volume.PruneReport{}, err } query, err := getFiltersQuery(pruneFilters) if err != nil { - return report, err + return volume.PruneReport{}, err } - serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) + resp, err := cli.post(ctx, "/volumes/prune", query, nil, nil) + defer ensureReaderClosed(resp) if err != nil { - return report, err + return volume.PruneReport{}, err } - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, fmt.Errorf("Error retrieving volume prune report: %v", err) + var report volume.PruneReport + if err := json.NewDecoder(resp.Body).Decode(&report); err != nil { + return volume.PruneReport{}, fmt.Errorf("Error retrieving volume prune report: %v", err) } return report, nil diff --git a/vendor/github.com/docker/docker/client/volume_remove.go b/vendor/github.com/docker/docker/client/volume_remove.go index b8bdc5ae8..eefd9ce43 100644 --- a/vendor/github.com/docker/docker/client/volume_remove.go +++ b/vendor/github.com/docker/docker/client/volume_remove.go @@ -9,6 +9,11 @@ import ( // VolumeRemove removes a volume from the docker host. func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error { + volumeID, err := trimID("volume", volumeID) + if err != nil { + return err + } + query := url.Values{} if force { // Make sure we negotiated (if the client is configured to do so), diff --git a/vendor/github.com/docker/docker/client/volume_update.go b/vendor/github.com/docker/docker/client/volume_update.go index 151863f07..c91d5e984 100644 --- a/vendor/github.com/docker/docker/client/volume_update.go +++ b/vendor/github.com/docker/docker/client/volume_update.go @@ -11,6 +11,10 @@ import ( // VolumeUpdate updates a volume. This only works for Cluster Volumes, and // only some fields can be updated. func (cli *Client) VolumeUpdate(ctx context.Context, volumeID string, version swarm.Version, options volume.UpdateOptions) error { + volumeID, err := trimID("volume", volumeID) + if err != nil { + return err + } if err := cli.NewVersionError(ctx, "1.42", "volume update"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/errdefs/helpers.go b/vendor/github.com/docker/docker/errdefs/helpers.go index 042de4b7b..ab76e6273 100644 --- a/vendor/github.com/docker/docker/errdefs/helpers.go +++ b/vendor/github.com/docker/docker/errdefs/helpers.go @@ -14,7 +14,9 @@ func (e errNotFound) Unwrap() error { return e.error } -// NotFound is a helper to create an error of the class with the same name from any error type +// NotFound creates an [ErrNotFound] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrNotFound], func NotFound(err error) error { if err == nil || IsNotFound(err) { return err @@ -34,7 +36,9 @@ func (e errInvalidParameter) Unwrap() error { return e.error } -// InvalidParameter is a helper to create an error of the class with the same name from any error type +// InvalidParameter creates an [ErrInvalidParameter] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrInvalidParameter], func InvalidParameter(err error) error { if err == nil || IsInvalidParameter(err) { return err @@ -54,7 +58,9 @@ func (e errConflict) Unwrap() error { return e.error } -// Conflict is a helper to create an error of the class with the same name from any error type +// Conflict creates an [ErrConflict] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrConflict], func Conflict(err error) error { if err == nil || IsConflict(err) { return err @@ -74,7 +80,9 @@ func (e errUnauthorized) Unwrap() error { return e.error } -// Unauthorized is a helper to create an error of the class with the same name from any error type +// Unauthorized creates an [ErrUnauthorized] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrUnauthorized], func Unauthorized(err error) error { if err == nil || IsUnauthorized(err) { return err @@ -94,7 +102,9 @@ func (e errUnavailable) Unwrap() error { return e.error } -// Unavailable is a helper to create an error of the class with the same name from any error type +// Unavailable creates an [ErrUnavailable] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrUnavailable], func Unavailable(err error) error { if err == nil || IsUnavailable(err) { return err @@ -114,7 +124,9 @@ func (e errForbidden) Unwrap() error { return e.error } -// Forbidden is a helper to create an error of the class with the same name from any error type +// Forbidden creates an [ErrForbidden] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrForbidden], func Forbidden(err error) error { if err == nil || IsForbidden(err) { return err @@ -134,7 +146,9 @@ func (e errSystem) Unwrap() error { return e.error } -// System is a helper to create an error of the class with the same name from any error type +// System creates an [ErrSystem] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrSystem], func System(err error) error { if err == nil || IsSystem(err) { return err @@ -154,7 +168,9 @@ func (e errNotModified) Unwrap() error { return e.error } -// NotModified is a helper to create an error of the class with the same name from any error type +// NotModified creates an [ErrNotModified] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [NotModified], func NotModified(err error) error { if err == nil || IsNotModified(err) { return err @@ -174,7 +190,9 @@ func (e errNotImplemented) Unwrap() error { return e.error } -// NotImplemented is a helper to create an error of the class with the same name from any error type +// NotImplemented creates an [ErrNotImplemented] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrNotImplemented], func NotImplemented(err error) error { if err == nil || IsNotImplemented(err) { return err @@ -194,7 +212,9 @@ func (e errUnknown) Unwrap() error { return e.error } -// Unknown is a helper to create an error of the class with the same name from any error type +// Unknown creates an [ErrUnknown] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrUnknown], func Unknown(err error) error { if err == nil || IsUnknown(err) { return err @@ -214,7 +234,9 @@ func (e errCancelled) Unwrap() error { return e.error } -// Cancelled is a helper to create an error of the class with the same name from any error type +// Cancelled creates an [ErrCancelled] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrCancelled], func Cancelled(err error) error { if err == nil || IsCancelled(err) { return err @@ -234,7 +256,9 @@ func (e errDeadline) Unwrap() error { return e.error } -// Deadline is a helper to create an error of the class with the same name from any error type +// Deadline creates an [ErrDeadline] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrDeadline], func Deadline(err error) error { if err == nil || IsDeadline(err) { return err @@ -254,7 +278,9 @@ func (e errDataLoss) Unwrap() error { return e.error } -// DataLoss is a helper to create an error of the class with the same name from any error type +// DataLoss creates an [ErrDataLoss] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrDataLoss], func DataLoss(err error) error { if err == nil || IsDataLoss(err) { return err diff --git a/vendor/github.com/docker/docker/errdefs/http_helpers.go b/vendor/github.com/docker/docker/errdefs/http_helpers.go index ebcd78930..0a8fadd48 100644 --- a/vendor/github.com/docker/docker/errdefs/http_helpers.go +++ b/vendor/github.com/docker/docker/errdefs/http_helpers.go @@ -11,36 +11,37 @@ func FromStatusCode(err error, statusCode int) error { } switch statusCode { case http.StatusNotFound: - err = NotFound(err) + return NotFound(err) case http.StatusBadRequest: - err = InvalidParameter(err) + return InvalidParameter(err) case http.StatusConflict: - err = Conflict(err) + return Conflict(err) case http.StatusUnauthorized: - err = Unauthorized(err) + return Unauthorized(err) case http.StatusServiceUnavailable: - err = Unavailable(err) + return Unavailable(err) case http.StatusForbidden: - err = Forbidden(err) + return Forbidden(err) case http.StatusNotModified: - err = NotModified(err) + return NotModified(err) case http.StatusNotImplemented: - err = NotImplemented(err) + return NotImplemented(err) case http.StatusInternalServerError: - if !IsSystem(err) && !IsUnknown(err) && !IsDataLoss(err) && !IsDeadline(err) && !IsCancelled(err) { - err = System(err) + if IsCancelled(err) || IsSystem(err) || IsUnknown(err) || IsDataLoss(err) || IsDeadline(err) { + return err } + return System(err) default: switch { case statusCode >= 200 && statusCode < 400: // it's a client error + return err case statusCode >= 400 && statusCode < 500: - err = InvalidParameter(err) + return InvalidParameter(err) case statusCode >= 500 && statusCode < 600: - err = System(err) + return System(err) default: - err = Unknown(err) + return Unknown(err) } } - return err } diff --git a/vendor/github.com/docker/docker/errdefs/is.go b/vendor/github.com/docker/docker/errdefs/is.go index f94034cbd..30ea7e6fe 100644 --- a/vendor/github.com/docker/docker/errdefs/is.go +++ b/vendor/github.com/docker/docker/errdefs/is.go @@ -39,79 +39,79 @@ func getImplementer(err error) error { } } -// IsNotFound returns if the passed in error is an ErrNotFound +// IsNotFound returns if the passed in error is an [ErrNotFound], func IsNotFound(err error) bool { _, ok := getImplementer(err).(ErrNotFound) return ok } -// IsInvalidParameter returns if the passed in error is an ErrInvalidParameter +// IsInvalidParameter returns if the passed in error is an [ErrInvalidParameter]. func IsInvalidParameter(err error) bool { _, ok := getImplementer(err).(ErrInvalidParameter) return ok } -// IsConflict returns if the passed in error is an ErrConflict +// IsConflict returns if the passed in error is an [ErrConflict]. func IsConflict(err error) bool { _, ok := getImplementer(err).(ErrConflict) return ok } -// IsUnauthorized returns if the passed in error is an ErrUnauthorized +// IsUnauthorized returns if the passed in error is an [ErrUnauthorized]. func IsUnauthorized(err error) bool { _, ok := getImplementer(err).(ErrUnauthorized) return ok } -// IsUnavailable returns if the passed in error is an ErrUnavailable +// IsUnavailable returns if the passed in error is an [ErrUnavailable]. func IsUnavailable(err error) bool { _, ok := getImplementer(err).(ErrUnavailable) return ok } -// IsForbidden returns if the passed in error is an ErrForbidden +// IsForbidden returns if the passed in error is an [ErrForbidden]. func IsForbidden(err error) bool { _, ok := getImplementer(err).(ErrForbidden) return ok } -// IsSystem returns if the passed in error is an ErrSystem +// IsSystem returns if the passed in error is an [ErrSystem]. func IsSystem(err error) bool { _, ok := getImplementer(err).(ErrSystem) return ok } -// IsNotModified returns if the passed in error is a NotModified error +// IsNotModified returns if the passed in error is an [ErrNotModified]. func IsNotModified(err error) bool { _, ok := getImplementer(err).(ErrNotModified) return ok } -// IsNotImplemented returns if the passed in error is an ErrNotImplemented +// IsNotImplemented returns if the passed in error is an [ErrNotImplemented]. func IsNotImplemented(err error) bool { _, ok := getImplementer(err).(ErrNotImplemented) return ok } -// IsUnknown returns if the passed in error is an ErrUnknown +// IsUnknown returns if the passed in error is an [ErrUnknown]. func IsUnknown(err error) bool { _, ok := getImplementer(err).(ErrUnknown) return ok } -// IsCancelled returns if the passed in error is an ErrCancelled +// IsCancelled returns if the passed in error is an [ErrCancelled]. func IsCancelled(err error) bool { _, ok := getImplementer(err).(ErrCancelled) return ok } -// IsDeadline returns if the passed in error is an ErrDeadline +// IsDeadline returns if the passed in error is an [ErrDeadline]. func IsDeadline(err error) bool { _, ok := getImplementer(err).(ErrDeadline) return ok } -// IsDataLoss returns if the passed in error is an ErrDataLoss +// IsDataLoss returns if the passed in error is an [ErrDataLoss]. func IsDataLoss(err error) bool { _, ok := getImplementer(err).(ErrDataLoss) return ok diff --git a/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go b/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go new file mode 100644 index 000000000..6334edb60 --- /dev/null +++ b/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go @@ -0,0 +1,90 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code below was largely copied from golang.org/x/mod@v0.22; +// https://github.com/golang/mod/blob/v0.22.0/internal/lazyregexp/lazyre.go +// with some additional methods added. + +// Package lazyregexp is a thin wrapper over regexp, allowing the use of global +// regexp variables without forcing them to be compiled at init. +package lazyregexp + +import ( + "os" + "regexp" + "strings" + "sync" +) + +// Regexp is a wrapper around [regexp.Regexp], where the underlying regexp will be +// compiled the first time it is needed. +type Regexp struct { + str string + once sync.Once + rx *regexp.Regexp +} + +func (r *Regexp) re() *regexp.Regexp { + r.once.Do(r.build) + return r.rx +} + +func (r *Regexp) build() { + r.rx = regexp.MustCompile(r.str) + r.str = "" +} + +func (r *Regexp) FindSubmatch(s []byte) [][]byte { + return r.re().FindSubmatch(s) +} + +func (r *Regexp) FindAllStringSubmatch(s string, n int) [][]string { + return r.re().FindAllStringSubmatch(s, n) +} + +func (r *Regexp) FindStringSubmatch(s string) []string { + return r.re().FindStringSubmatch(s) +} + +func (r *Regexp) FindStringSubmatchIndex(s string) []int { + return r.re().FindStringSubmatchIndex(s) +} + +func (r *Regexp) ReplaceAllString(src, repl string) string { + return r.re().ReplaceAllString(src, repl) +} + +func (r *Regexp) FindString(s string) string { + return r.re().FindString(s) +} + +func (r *Regexp) FindAllString(s string, n int) []string { + return r.re().FindAllString(s, n) +} + +func (r *Regexp) MatchString(s string) bool { + return r.re().MatchString(s) +} + +func (r *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string { + return r.re().ReplaceAllStringFunc(src, repl) +} + +func (r *Regexp) SubexpNames() []string { + return r.re().SubexpNames() +} + +var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test") + +// New creates a new lazy regexp, delaying the compiling work until it is first +// needed. If the code is being run as part of tests, the regexp compiling will +// happen immediately. +func New(str string) *Regexp { + lr := &Regexp{str: str} + if inTest { + // In tests, always compile the regexps early. + lr.re() + } + return lr +} diff --git a/vendor/github.com/docker/docker/pkg/archive/archive.go b/vendor/github.com/docker/docker/pkg/archive/archive.go index cde64f08e..b05780406 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive.go @@ -1,5 +1,5 @@ // Package archive provides helper functions for dealing with archive files. -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "archive/tar" @@ -9,26 +9,26 @@ import ( "compress/gzip" "context" "encoding/binary" + "errors" "fmt" "io" "os" "os/exec" "path/filepath" "runtime" + "runtime/debug" "strconv" "strings" + "sync" + "sync/atomic" "syscall" "time" "github.com/containerd/log" "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/pools" - "github.com/docker/docker/pkg/system" "github.com/klauspost/compress/zstd" "github.com/moby/patternmatcher" "github.com/moby/sys/sequential" - "github.com/pkg/errors" ) // ImpliedDirectoryMode represents the mode (Unix permissions) applied to directories that are implied by files in a @@ -215,17 +215,66 @@ func gzDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) { return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf) } -func wrapReadCloser(readBuf io.ReadCloser, cancel context.CancelFunc) io.ReadCloser { - return ioutils.NewReadCloserWrapper(readBuf, func() error { - cancel() - return readBuf.Close() - }) +type readCloserWrapper struct { + io.Reader + closer func() error + closed atomic.Bool +} + +func (r *readCloserWrapper) Close() error { + if !r.closed.CompareAndSwap(false, true) { + log.G(context.TODO()).Error("subsequent attempt to close readCloserWrapper") + if log.GetLevel() >= log.DebugLevel { + log.G(context.TODO()).Errorf("stack trace: %s", string(debug.Stack())) + } + + return nil + } + if r.closer != nil { + return r.closer() + } + return nil +} + +var ( + bufioReader32KPool = &sync.Pool{ + New: func() interface{} { return bufio.NewReaderSize(nil, 32*1024) }, + } +) + +type bufferedReader struct { + buf *bufio.Reader +} + +func newBufferedReader(r io.Reader) *bufferedReader { + buf := bufioReader32KPool.Get().(*bufio.Reader) + buf.Reset(r) + return &bufferedReader{buf} +} + +func (r *bufferedReader) Read(p []byte) (n int, err error) { + if r.buf == nil { + return 0, io.EOF + } + n, err = r.buf.Read(p) + if err == io.EOF { + r.buf.Reset(nil) + bufioReader32KPool.Put(r.buf) + r.buf = nil + } + return +} + +func (r *bufferedReader) Peek(n int) ([]byte, error) { + if r.buf == nil { + return nil, io.EOF + } + return r.buf.Peek(n) } // DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive. func DecompressStream(archive io.Reader) (io.ReadCloser, error) { - p := pools.BufioReader32KPool - buf := p.Get(archive) + buf := newBufferedReader(archive) bs, err := buf.Peek(10) if err != nil && err != io.EOF { // Note: we'll ignore any io.EOF error because there are some odd @@ -240,8 +289,9 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) { compression := DetectCompression(bs) switch compression { case Uncompressed: - readBufWrapper := p.NewReadCloserWrapper(buf, buf) - return readBufWrapper, nil + return &readCloserWrapper{ + Reader: buf, + }, nil case Gzip: ctx, cancel := context.WithCancel(context.Background()) @@ -250,12 +300,18 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) { cancel() return nil, err } - readBufWrapper := p.NewReadCloserWrapper(buf, gzReader) - return wrapReadCloser(readBufWrapper, cancel), nil + return &readCloserWrapper{ + Reader: gzReader, + closer: func() error { + cancel() + return gzReader.Close() + }, + }, nil case Bzip2: bz2Reader := bzip2.NewReader(buf) - readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader) - return readBufWrapper, nil + return &readCloserWrapper{ + Reader: bz2Reader, + }, nil case Xz: ctx, cancel := context.WithCancel(context.Background()) @@ -264,32 +320,44 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) { cancel() return nil, err } - readBufWrapper := p.NewReadCloserWrapper(buf, xzReader) - return wrapReadCloser(readBufWrapper, cancel), nil + + return &readCloserWrapper{ + Reader: xzReader, + closer: func() error { + cancel() + return xzReader.Close() + }, + }, nil case Zstd: zstdReader, err := zstd.NewReader(buf) if err != nil { return nil, err } - readBufWrapper := p.NewReadCloserWrapper(buf, zstdReader) - return readBufWrapper, nil + return &readCloserWrapper{ + Reader: zstdReader, + closer: func() error { + zstdReader.Close() + return nil + }, + }, nil default: return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) } } +type nopWriteCloser struct { + io.Writer +} + +func (nopWriteCloser) Close() error { return nil } + // CompressStream compresses the dest with specified compression algorithm. func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) { - p := pools.BufioWriter32KPool - buf := p.Get(dest) switch compression { case Uncompressed: - writeBufWrapper := p.NewWriteCloserWrapper(buf, buf) - return writeBufWrapper, nil + return nopWriteCloser{dest}, nil case Gzip: - gzWriter := gzip.NewWriter(dest) - writeBufWrapper := p.NewWriteCloserWrapper(buf, gzWriter) - return writeBufWrapper, nil + return gzip.NewWriter(dest), nil case Bzip2, Xz: // archive/bzip2 does not support writing, and there is no xz support at all // However, this is not a problem as docker only currently generates gzipped tars @@ -360,7 +428,7 @@ func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModi pipeWriter.CloseWithError(err) return } - if _, err := pools.Copy(tarWriter, tarReader); err != nil { + if _, err := copyWithBuffer(tarWriter, tarReader); err != nil { pipeWriter.CloseWithError(err) return } @@ -404,13 +472,35 @@ func (compression *Compression) Extension() string { return "" } +// assert that we implement [tar.FileInfoNames]. +// +// TODO(thaJeztah): disabled to allow compiling on < go1.23. un-comment once we drop support for older versions of go. +// var _ tar.FileInfoNames = (*nosysFileInfo)(nil) + // nosysFileInfo hides the system-dependent info of the wrapped FileInfo to // prevent tar.FileInfoHeader from introspecting it and potentially calling into // glibc. +// +// It implements [tar.FileInfoNames] to further prevent [tar.FileInfoHeader] +// from performing any lookups on go1.23 and up. see https://go.dev/issue/50102 type nosysFileInfo struct { os.FileInfo } +// Uname stubs out looking up username. It implements [tar.FileInfoNames] +// to prevent [tar.FileInfoHeader] from loading libraries to perform +// username lookups. +func (fi nosysFileInfo) Uname() (string, error) { + return "", nil +} + +// Gname stubs out looking up group-name. It implements [tar.FileInfoNames] +// to prevent [tar.FileInfoHeader] from loading libraries to perform +// username lookups. +func (fi nosysFileInfo) Gname() (string, error) { + return "", nil +} + func (fi nosysFileInfo) Sys() interface{} { // A Sys value of type *tar.Header is safe as it is system-independent. // The tar.FileInfoHeader function copies the fields into the returned @@ -484,7 +574,7 @@ func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error { vfsCapRevision2 = 2 vfsCapRevision3 = 3 ) - capability, _ := system.Lgetxattr(path, "security.capability") + capability, _ := lgetxattr(path, "security.capability") if capability != nil { if capability[versionOffset] == vfsCapRevision3 { // Convert VFS_CAP_REVISION_3 to VFS_CAP_REVISION_2 as root UID makes no @@ -507,7 +597,6 @@ type tarWhiteoutConverter interface { type tarAppender struct { TarWriter *tar.Writer - Buffer *bufio.Writer // for hardlink mapping SeenFiles map[uint64]string @@ -525,21 +614,11 @@ func newTarAppender(idMapping idtools.IdentityMapping, writer io.Writer, chownOp return &tarAppender{ SeenFiles: make(map[uint64]string), TarWriter: tar.NewWriter(writer), - Buffer: pools.BufioWriter32KPool.Get(nil), IdentityMapping: idMapping, ChownOpts: chownOpts, } } -// CanonicalTarNameForPath canonicalizes relativePath to a POSIX-style path using -// forward slashes. It is an alias for [filepath.ToSlash], which is a no-op on -// Linux and Unix. -// -// Deprecated: use [filepath.ToSlash]. This function will be removed in the next release. -func CanonicalTarNameForPath(relativePath string) string { - return filepath.ToSlash(relativePath) -} - // canonicalTarName provides a platform-independent and consistent POSIX-style // path for files and directories to be archived regardless of the platform. func canonicalTarName(name string, isDir bool) string { @@ -652,17 +731,11 @@ func (ta *tarAppender) addTarFile(path, name string) error { return err } - ta.Buffer.Reset(ta.TarWriter) - defer ta.Buffer.Reset(nil) - _, err = io.Copy(ta.Buffer, file) + _, err = copyWithBuffer(ta.TarWriter, file) file.Close() if err != nil { return err } - err = ta.Buffer.Flush() - if err != nil { - return err - } } return nil @@ -705,7 +778,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o if err != nil { return err } - if _, err := io.Copy(file, reader); err != nil { + if _, err := copyWithBuffer(file, reader); err != nil { file.Close() return err } @@ -771,11 +844,11 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o chownOpts = &idtools.Identity{UID: hdr.Uid, GID: hdr.Gid} } if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil { - msg := "failed to Lchown %q for UID %d, GID %d" + var msg string if inUserns && errors.Is(err, syscall.EINVAL) { - msg += " (try increasing the number of subordinate IDs in /etc/subuid and /etc/subgid)" + msg = " (try increasing the number of subordinate IDs in /etc/subuid and /etc/subgid)" } - return errors.Wrapf(err, msg, path, hdr.Uid, hdr.Gid) + return fmt.Errorf("failed to Lchown %q for UID %d, GID %d%s: %w", path, hdr.Uid, hdr.Gid, msg, err) } } @@ -785,7 +858,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o if !ok { continue } - if err := system.Lsetxattr(path, xattr, []byte(value), 0); err != nil { + if err := lsetxattr(path, xattr, []byte(value), 0); err != nil { if bestEffortXattrs && errors.Is(err, syscall.ENOTSUP) || errors.Is(err, syscall.EPERM) { // EPERM occurs if modifying xattrs is not allowed. This can // happen when running in userns with restrictions (ChromeOS). @@ -808,26 +881,22 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o return err } - aTime := hdr.AccessTime - if aTime.Before(hdr.ModTime) { - // Last access time should never be before last modified time. - aTime = hdr.ModTime - } + aTime := boundTime(latestTime(hdr.AccessTime, hdr.ModTime)) + mTime := boundTime(hdr.ModTime) - // system.Chtimes doesn't support a NOFOLLOW flag atm + // chtimes doesn't support a NOFOLLOW flag atm if hdr.Typeflag == tar.TypeLink { if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) { - if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil { + if err := chtimes(path, aTime, mTime); err != nil { return err } } } else if hdr.Typeflag != tar.TypeSymlink { - if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil { + if err := chtimes(path, aTime, mTime); err != nil { return err } } else { - ts := []syscall.Timespec{timeToTimespec(aTime), timeToTimespec(hdr.ModTime)} - if err := system.LUtimesNano(path, ts); err != nil && err != system.ErrNotSupportedPlatform { + if err := lchtimes(path, aTime, mTime); err != nil { return err } } @@ -920,9 +989,6 @@ func (t *Tarballer) Do() { } }() - // this buffer is needed for the duration of this piped stream - defer pools.BufioWriter32KPool.Put(ta.Buffer) - // In general we log errors here but ignore them because // during e.g. a diff operation the container can continue // mutating the filesystem and we can see transient errors @@ -1078,8 +1144,6 @@ func (t *Tarballer) Do() { // Unpack unpacks the decompressedArchive to dest with options. func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) error { tr := tar.NewReader(decompressedArchive) - trBuf := pools.BufioReader32KPool.Get(nil) - defer pools.BufioReader32KPool.Put(trBuf) var dirs []*tar.Header whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat) @@ -1156,7 +1220,6 @@ loop: } } } - trBuf.Reset(tr) if err := remapIDs(options.IDMap, hdr); err != nil { return err @@ -1172,7 +1235,7 @@ loop: } } - if err := createTarFile(path, dest, hdr, trBuf, options); err != nil { + if err := createTarFile(path, dest, hdr, tr, options); err != nil { return err } @@ -1187,7 +1250,7 @@ loop: // #nosec G305 -- The header was checked for path traversal before it was appended to the dirs slice. path := filepath.Join(dest, hdr.Name) - if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { + if err := chtimes(path, boundTime(latestTime(hdr.AccessTime, hdr.ModTime)), boundTime(hdr.ModTime)); err != nil { return err } } @@ -1336,7 +1399,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) { dst = filepath.Join(dst, filepath.Base(src)) } // Create the holding directory if necessary - if err := system.MkdirAll(filepath.Dir(dst), 0o700); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), 0o700); err != nil { return err } @@ -1375,7 +1438,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) { if err := tw.WriteHeader(hdr); err != nil { return err } - if _, err := io.Copy(tw, srcF); err != nil { + if _, err := copyWithBuffer(tw, srcF); err != nil { return err } return nil @@ -1433,68 +1496,14 @@ func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, error) { close(done) }() - return ioutils.NewReadCloserWrapper(pipeR, func() error { - // Close pipeR, and then wait for the command to complete before returning. We have to close pipeR first, as - // cmd.Wait waits for any non-file stdout/stderr/stdin to close. - err := pipeR.Close() - <-done - return err - }), nil -} - -// NewTempArchive reads the content of src into a temporary file, and returns the contents -// of that file as an archive. The archive can only be read once - as soon as reading completes, -// the file will be deleted. -// -// Deprecated: NewTempArchive is only used in tests and will be removed in the next release. -func NewTempArchive(src io.Reader, dir string) (*TempArchive, error) { - f, err := os.CreateTemp(dir, "") - if err != nil { - return nil, err - } - if _, err := io.Copy(f, src); err != nil { - return nil, err - } - if _, err := f.Seek(0, 0); err != nil { - return nil, err - } - st, err := f.Stat() - if err != nil { - return nil, err - } - size := st.Size() - return &TempArchive{File: f, Size: size}, nil -} - -// TempArchive is a temporary archive. The archive can only be read once - as soon as reading completes, -// the file will be deleted. -// -// Deprecated: TempArchive is only used in tests and will be removed in the next release. -type TempArchive struct { - *os.File - Size int64 // Pre-computed from Stat().Size() as a convenience - read int64 - closed bool -} - -// Close closes the underlying file if it's still open, or does a no-op -// to allow callers to try to close the TempArchive multiple times safely. -func (archive *TempArchive) Close() error { - if archive.closed { - return nil - } - - archive.closed = true - - return archive.File.Close() -} - -func (archive *TempArchive) Read(data []byte) (int, error) { - n, err := archive.File.Read(data) - archive.read += int64(n) - if err != nil || archive.read == archive.Size { - archive.Close() - os.Remove(archive.File.Name()) - } - return n, err + return &readCloserWrapper{ + Reader: pipeR, + closer: func() error { + // Close pipeR, and then wait for the command to complete before returning. We have to close pipeR first, as + // cmd.Wait waits for any non-file stdout/stderr/stdin to close. + err := pipeR.Close() + <-done + return err + }, + }, nil } diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go b/vendor/github.com/docker/docker/pkg/archive/archive_linux.go index 45ac2aa6c..631d2e3c5 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_linux.go @@ -1,14 +1,13 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "archive/tar" + "fmt" "os" "path/filepath" "strings" - "github.com/containerd/containerd/pkg/userns" - "github.com/docker/docker/pkg/system" - "github.com/pkg/errors" + "github.com/moby/sys/userns" "golang.org/x/sys/unix" ) @@ -39,7 +38,7 @@ func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os } // convert opaque dirs to AUFS format by writing an empty file with the prefix - opaque, err := system.Lgetxattr(path, opaqueXattrName) + opaque, err := lgetxattr(path, opaqueXattrName) if err != nil { return nil, err } @@ -79,7 +78,7 @@ func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (boo err := unix.Setxattr(dir, opaqueXattrName, []byte{'y'}, 0) if err != nil { - return false, errors.Wrapf(err, "setxattr(%q, %s=y)", dir, opaqueXattrName) + return false, fmt.Errorf("setxattr('%s', %s=y): %w", dir, opaqueXattrName, err) } // don't write the file itself return false, err @@ -91,7 +90,7 @@ func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (boo originalPath := filepath.Join(dir, originalBase) if err := unix.Mknod(originalPath, unix.S_IFCHR, 0); err != nil { - return false, errors.Wrapf(err, "failed to mknod(%q, S_IFCHR, 0)", originalPath) + return false, fmt.Errorf("failed to mknod('%s', S_IFCHR, 0): %w", originalPath, err) } if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil { return false, err diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_other.go b/vendor/github.com/docker/docker/pkg/archive/archive_other.go index 7dee1f7a4..6495549f6 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_other.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_other.go @@ -1,6 +1,6 @@ //go:build !linux -package archive // import "github.com/docker/docker/pkg/archive" +package archive func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter { return nil diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go b/vendor/github.com/docker/docker/pkg/archive/archive_unix.go index f559a3056..9c70d1789 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_unix.go @@ -1,6 +1,6 @@ //go:build !windows -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "archive/tar" @@ -12,7 +12,6 @@ import ( "syscall" "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/system" "golang.org/x/sys/unix" ) @@ -109,7 +108,7 @@ func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { mode |= unix.S_IFIFO } - return system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor))) + return mknod(path, mode, unix.Mkdev(uint32(hdr.Devmajor), uint32(hdr.Devminor))) } func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go b/vendor/github.com/docker/docker/pkg/archive/archive_windows.go index e25c64b41..031608162 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_windows.go @@ -1,4 +1,4 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "archive/tar" diff --git a/vendor/github.com/docker/docker/pkg/archive/changes.go b/vendor/github.com/docker/docker/pkg/archive/changes.go index 5f12ca401..79c810a68 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes.go @@ -1,4 +1,4 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "archive/tar" @@ -6,17 +6,15 @@ import ( "context" "fmt" "io" + "io/fs" "os" "path/filepath" "sort" "strings" - "syscall" "time" "github.com/containerd/log" "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/pools" - "github.com/docker/docker/pkg/system" ) // ChangeType represents the change type. @@ -74,11 +72,6 @@ func sameFsTime(a, b time.Time) bool { (a.Nanosecond() == 0 || b.Nanosecond() == 0)) } -func sameFsTimeSpec(a, b syscall.Timespec) bool { - return a.Sec == b.Sec && - (a.Nsec == b.Nsec || a.Nsec == 0 || b.Nsec == 0) -} - // Changes walks the path rw and determines changes for the files in the path, // with respect to the parent layers func Changes(layers []string, rw string) ([]Change, error) { @@ -210,7 +203,7 @@ func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Chan type FileInfo struct { parent *FileInfo name string - stat *system.StatT + stat fs.FileInfo children map[string]*FileInfo capability []byte added bool @@ -395,9 +388,6 @@ func ExportChanges(dir string, changes []Change, idMap idtools.IdentityMapping) go func() { ta := newTarAppender(idMap, writer, nil) - // this buffer is needed for the duration of this piped stream - defer pools.BufioWriter32KPool.Put(ta.Buffer) - sort.Sort(changesByPath(changes)) // In general we log errors here but ignore them because diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go b/vendor/github.com/docker/docker/pkg/archive/changes_linux.go index 81fcbc5ba..9a041b098 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes_linux.go @@ -1,15 +1,14 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( - "bytes" "fmt" "os" "path/filepath" "sort" + "strings" "syscall" "unsafe" - "github.com/docker/docker/pkg/system" "golang.org/x/sys/unix" ) @@ -74,12 +73,8 @@ func walkchunk(path string, fi os.FileInfo, dir string, root *FileInfo) error { parent: parent, } cpath := filepath.Join(dir, path) - stat, err := system.FromStatT(fi.Sys().(*syscall.Stat_t)) - if err != nil { - return err - } - info.stat = stat - info.capability, _ = system.Lgetxattr(cpath, "security.capability") // lgetxattr(2): fs access + info.stat = fi + info.capability, _ = lgetxattr(cpath, "security.capability") // lgetxattr(2): fs access parent.children[info.name] = info return nil } @@ -148,7 +143,7 @@ func (w *walker) walk(path string, i1, i2 os.FileInfo) (err error) { ni1 := names1[ix1] ni2 := names2[ix2] - switch bytes.Compare([]byte(ni1.name), []byte(ni2.name)) { + switch strings.Compare(ni1.name, ni2.name) { case -1: // ni1 < ni2 -- advance ni1 // we will not encounter ni1 in names2 names = append(names, ni1.name) @@ -261,13 +256,13 @@ func readdirnames(dirname string) (names []nameIno, err error) { func parseDirent(buf []byte, names []nameIno) (consumed int, newnames []nameIno) { origlen := len(buf) for len(buf) > 0 { - dirent := (*unix.Dirent)(unsafe.Pointer(&buf[0])) + dirent := (*unix.Dirent)(unsafe.Pointer(&buf[0])) // #nosec G103 -- Ignore "G103: Use of unsafe calls should be audited" buf = buf[dirent.Reclen:] if dirent.Ino == 0 { // File absent in directory. continue } - bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) - name := string(bytes[0:clen(bytes[:])]) + b := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) // #nosec G103 -- Ignore "G103: Use of unsafe calls should be audited" + name := string(b[0:clen(b[:])]) if name == "." || name == ".." { // Useless names continue } diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_other.go b/vendor/github.com/docker/docker/pkg/archive/changes_other.go index 28f741a25..a8a3a5a6f 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes_other.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes_other.go @@ -1,6 +1,6 @@ //go:build !linux -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "fmt" @@ -8,8 +8,6 @@ import ( "path/filepath" "runtime" "strings" - - "github.com/docker/docker/pkg/system" ) func collectFileInfoForChanges(oldDir, newDir string) (*FileInfo, *FileInfo, error) { @@ -72,7 +70,7 @@ func collectFileInfo(sourceDir string) (*FileInfo, error) { return fmt.Errorf("collectFileInfo: Unexpectedly no parent for %s", relPath) } - s, err := system.Lstat(path) + s, err := os.Lstat(path) if err != nil { return err } @@ -84,11 +82,7 @@ func collectFileInfo(sourceDir string) (*FileInfo, error) { stat: s, } - // system.Lgetxattr is only implemented on Linux and produces an error - // on other platforms. This code is intentionally left commented-out - // as a reminder to include this code if this would ever be implemented - // on other platforms. - // info.capability, _ = system.Lgetxattr(path, "security.capability") + info.capability, _ = lgetxattr(path, "security.capability") parent.children[info.name] = info diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go b/vendor/github.com/docker/docker/pkg/archive/changes_unix.go index 853c73ee8..4dd98bd29 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes_unix.go @@ -1,21 +1,21 @@ //go:build !windows -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( + "io/fs" "os" "syscall" - - "github.com/docker/docker/pkg/system" - "golang.org/x/sys/unix" ) -func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { +func statDifferent(oldStat fs.FileInfo, newStat fs.FileInfo) bool { + oldSys := oldStat.Sys().(*syscall.Stat_t) + newSys := newStat.Sys().(*syscall.Stat_t) // Don't look at size for dirs, its not a good measure of change if oldStat.Mode() != newStat.Mode() || - oldStat.UID() != newStat.UID() || - oldStat.GID() != newStat.GID() || - oldStat.Rdev() != newStat.Rdev() || + oldSys.Uid != newSys.Uid || + oldSys.Gid != newSys.Gid || + oldSys.Rdev != newSys.Rdev || // Don't look at size or modification time for dirs, its not a good // measure of change. See https://github.com/moby/moby/issues/9874 // for a description of the issue with modification time, and @@ -23,15 +23,15 @@ func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { // (Note that in the Windows implementation of this function, // modification time IS taken as a change). See // https://github.com/moby/moby/pull/37982 for more information. - (oldStat.Mode()&unix.S_IFDIR != unix.S_IFDIR && - (!sameFsTimeSpec(oldStat.Mtim(), newStat.Mtim()) || (oldStat.Size() != newStat.Size()))) { + (!oldStat.Mode().IsDir() && + (!sameFsTime(oldStat.ModTime(), newStat.ModTime()) || (oldStat.Size() != newStat.Size()))) { return true } return false } func (info *FileInfo) isDir() bool { - return info.parent == nil || info.stat.Mode()&unix.S_IFDIR != 0 + return info.parent == nil || info.stat.Mode().IsDir() } func getIno(fi os.FileInfo) uint64 { diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go b/vendor/github.com/docker/docker/pkg/archive/changes_windows.go index 9906685e4..c89605c78 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes_windows.go @@ -1,19 +1,18 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( + "io/fs" "os" - - "github.com/docker/docker/pkg/system" ) -func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { +func statDifferent(oldStat fs.FileInfo, newStat fs.FileInfo) bool { // Note there is slight difference between the Linux and Windows // implementations here. Due to https://github.com/moby/moby/issues/9874, // and the fix at https://github.com/moby/moby/pull/11422, Linux does not // consider a change to the directory time as a change. Windows on NTFS // does. See https://github.com/moby/moby/pull/37982 for more information. - if !sameFsTime(oldStat.Mtim(), newStat.Mtim()) || + if !sameFsTime(oldStat.ModTime(), newStat.ModTime()) || oldStat.Mode() != newStat.Mode() || oldStat.Size() != newStat.Size() && !oldStat.Mode().IsDir() { return true diff --git a/vendor/github.com/docker/docker/pkg/archive/copy.go b/vendor/github.com/docker/docker/pkg/archive/copy.go index 01eadc30d..cddf18ecd 100644 --- a/vendor/github.com/docker/docker/pkg/archive/copy.go +++ b/vendor/github.com/docker/docker/pkg/archive/copy.go @@ -1,4 +1,4 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "archive/tar" @@ -8,9 +8,9 @@ import ( "os" "path/filepath" "strings" + "sync" "github.com/containerd/log" - "github.com/docker/docker/pkg/system" ) // Errors used or returned by this file. @@ -21,6 +21,17 @@ var ( ErrInvalidCopySource = errors.New("invalid copy source content") ) +var copyPool = sync.Pool{ + New: func() interface{} { s := make([]byte, 32*1024); return &s }, +} + +func copyWithBuffer(dst io.Writer, src io.Reader) (written int64, err error) { + buf := copyPool.Get().(*[]byte) + written, err = io.CopyBuffer(dst, src, *buf) + copyPool.Put(buf) + return +} + // PreserveTrailingDotOrSeparator returns the given cleaned path (after // processing using any utility functions from the path or filepath stdlib // packages) and appends a trailing `/.` or `/` if its corresponding original @@ -203,7 +214,7 @@ func CopyInfoDestinationPath(path string) (info CopyInfo, err error) { return CopyInfo{}, err } - if !system.IsAbs(linkTarget) { + if !filepath.IsAbs(linkTarget) { // Join with the parent directory. dstParent, _ := SplitPathDirEntry(path) linkTarget = filepath.Join(dstParent, linkTarget) diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go b/vendor/github.com/docker/docker/pkg/archive/copy_unix.go index 065bd4add..f57928244 100644 --- a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go +++ b/vendor/github.com/docker/docker/pkg/archive/copy_unix.go @@ -1,6 +1,6 @@ //go:build !windows -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "path/filepath" diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go b/vendor/github.com/docker/docker/pkg/archive/copy_windows.go index a878d1bac..2b775b45c 100644 --- a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go +++ b/vendor/github.com/docker/docker/pkg/archive/copy_windows.go @@ -1,4 +1,4 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "path/filepath" diff --git a/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go b/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go new file mode 100644 index 000000000..aa8e29154 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go @@ -0,0 +1,7 @@ +//go:build freebsd + +package archive + +import "golang.org/x/sys/unix" + +var mknod = unix.Mknod diff --git a/vendor/github.com/docker/docker/pkg/archive/dev_unix.go b/vendor/github.com/docker/docker/pkg/archive/dev_unix.go new file mode 100644 index 000000000..dffc596f9 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/dev_unix.go @@ -0,0 +1,9 @@ +//go:build !windows && !freebsd + +package archive + +import "golang.org/x/sys/unix" + +func mknod(path string, mode uint32, dev uint64) error { + return unix.Mknod(path, mode, int(dev)) +} diff --git a/vendor/github.com/docker/docker/pkg/archive/diff.go b/vendor/github.com/docker/docker/pkg/archive/diff.go index e080e310a..d5a394cdc 100644 --- a/vendor/github.com/docker/docker/pkg/archive/diff.go +++ b/vendor/github.com/docker/docker/pkg/archive/diff.go @@ -1,4 +1,4 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "archive/tar" @@ -11,8 +11,6 @@ import ( "strings" "github.com/containerd/log" - "github.com/docker/docker/pkg/pools" - "github.com/docker/docker/pkg/system" ) // UnpackLayer unpack `layer` to a `dest`. The stream `layer` can be @@ -20,8 +18,6 @@ import ( // Returns the size in bytes of the contents of the layer. func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, err error) { tr := tar.NewReader(layer) - trBuf := pools.BufioReader32KPool.Get(tr) - defer pools.BufioReader32KPool.Put(trBuf) var dirs []*tar.Header unpackedPaths := make(map[string]struct{}) @@ -160,8 +156,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, } } - trBuf.Reset(tr) - srcData := io.Reader(trBuf) + srcData := io.Reader(tr) srcHdr := hdr // Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so @@ -200,7 +195,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, for _, hdr := range dirs { // #nosec G305 -- The header was checked for path traversal before it was appended to the dirs slice. path := filepath.Join(dest, hdr.Name) - if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { + if err := chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { return 0, err } } diff --git a/vendor/github.com/docker/docker/pkg/archive/time.go b/vendor/github.com/docker/docker/pkg/archive/time.go new file mode 100644 index 000000000..4e9ae9508 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/time.go @@ -0,0 +1,38 @@ +package archive + +import ( + "syscall" + "time" + "unsafe" +) + +var ( + minTime = time.Unix(0, 0) + maxTime time.Time +) + +func init() { + if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 { + // This is a 64 bit timespec + // os.Chtimes limits time to the following + maxTime = time.Unix(0, 1<<63-1) + } else { + // This is a 32 bit timespec + maxTime = time.Unix(1<<31-1, 0) + } +} + +func boundTime(t time.Time) time.Time { + if t.Before(minTime) || t.After(maxTime) { + return minTime + } + + return t +} + +func latestTime(t1, t2 time.Time) time.Time { + if t1.Before(t2) { + return t2 + } + return t1 +} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_linux.go b/vendor/github.com/docker/docker/pkg/archive/time_linux.go deleted file mode 100644 index 797143ee8..000000000 --- a/vendor/github.com/docker/docker/pkg/archive/time_linux.go +++ /dev/null @@ -1,16 +0,0 @@ -package archive // import "github.com/docker/docker/pkg/archive" - -import ( - "syscall" - "time" -) - -func timeToTimespec(time time.Time) (ts syscall.Timespec) { - if time.IsZero() { - // Return UTIME_OMIT special value - ts.Sec = 0 - ts.Nsec = (1 << 30) - 2 - return - } - return syscall.NsecToTimespec(time.UnixNano()) -} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go b/vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go new file mode 100644 index 000000000..8ce83bd0b --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go @@ -0,0 +1,40 @@ +//go:build !windows + +package archive + +import ( + "os" + "time" + + "golang.org/x/sys/unix" +) + +// chtimes changes the access time and modified time of a file at the given path. +// If the modified time is prior to the Unix Epoch (unixMinTime), or after the +// end of Unix Time (unixEpochTime), os.Chtimes has undefined behavior. In this +// case, Chtimes defaults to Unix Epoch, just in case. +func chtimes(name string, atime time.Time, mtime time.Time) error { + return os.Chtimes(name, atime, mtime) +} + +func timeToTimespec(time time.Time) (ts unix.Timespec) { + if time.IsZero() { + // Return UTIME_OMIT special value + ts.Sec = 0 + ts.Nsec = (1 << 30) - 2 + return + } + return unix.NsecToTimespec(time.UnixNano()) +} + +func lchtimes(name string, atime time.Time, mtime time.Time) error { + utimes := [2]unix.Timespec{ + timeToTimespec(atime), + timeToTimespec(mtime), + } + err := unix.UtimesNanoAt(unix.AT_FDCWD, name, utimes[0:], unix.AT_SYMLINK_NOFOLLOW) + if err != nil && err != unix.ENOSYS { + return err + } + return err +} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go b/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go deleted file mode 100644 index 14c4ceb1d..000000000 --- a/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !linux - -package archive // import "github.com/docker/docker/pkg/archive" - -import ( - "syscall" - "time" -) - -func timeToTimespec(time time.Time) (ts syscall.Timespec) { - nsec := int64(0) - if !time.IsZero() { - nsec = time.UnixNano() - } - return syscall.NsecToTimespec(nsec) -} diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go b/vendor/github.com/docker/docker/pkg/archive/time_windows.go similarity index 50% rename from vendor/github.com/docker/docker/pkg/system/chtimes_windows.go rename to vendor/github.com/docker/docker/pkg/archive/time_windows.go index ab478f5c3..af1f7c8f3 100644 --- a/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go +++ b/vendor/github.com/docker/docker/pkg/archive/time_windows.go @@ -1,15 +1,18 @@ -package system // import "github.com/docker/docker/pkg/system" +package archive import ( + "os" "time" "golang.org/x/sys/windows" ) -// setCTime will set the create time on a file. On Windows, this requires -// calling SetFileTime and explicitly including the create time. -func setCTime(path string, ctime time.Time) error { - pathp, err := windows.UTF16PtrFromString(path) +func chtimes(name string, atime time.Time, mtime time.Time) error { + if err := os.Chtimes(name, atime, mtime); err != nil { + return err + } + + pathp, err := windows.UTF16PtrFromString(name) if err != nil { return err } @@ -20,6 +23,10 @@ func setCTime(path string, ctime time.Time) error { return err } defer windows.Close(h) - c := windows.NsecToFiletime(ctime.UnixNano()) + c := windows.NsecToFiletime(mtime.UnixNano()) return windows.SetFileTime(h, &c, nil, nil) } + +func lchtimes(name string, atime time.Time, mtime time.Time) error { + return nil +} diff --git a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go b/vendor/github.com/docker/docker/pkg/archive/whiteouts.go index 4c072a87e..d20478a10 100644 --- a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go +++ b/vendor/github.com/docker/docker/pkg/archive/whiteouts.go @@ -1,4 +1,4 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive // Whiteouts are files with a special meaning for the layered filesystem. // Docker uses AUFS whiteout files inside exported archives. In other diff --git a/vendor/github.com/docker/docker/pkg/archive/wrap.go b/vendor/github.com/docker/docker/pkg/archive/wrap.go index 032db82ce..903befd76 100644 --- a/vendor/github.com/docker/docker/pkg/archive/wrap.go +++ b/vendor/github.com/docker/docker/pkg/archive/wrap.go @@ -1,4 +1,4 @@ -package archive // import "github.com/docker/docker/pkg/archive" +package archive import ( "archive/tar" diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported.go b/vendor/github.com/docker/docker/pkg/archive/xattr_supported.go new file mode 100644 index 000000000..652a1f0f3 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/xattr_supported.go @@ -0,0 +1,52 @@ +//go:build linux || darwin || freebsd || netbsd + +package archive + +import ( + "errors" + "fmt" + "io/fs" + + "golang.org/x/sys/unix" +) + +// lgetxattr retrieves the value of the extended attribute identified by attr +// and associated with the given path in the file system. +// It returns a nil slice and nil error if the xattr is not set. +func lgetxattr(path string, attr string) ([]byte, error) { + // Start with a 128 length byte array + dest := make([]byte, 128) + sz, err := unix.Lgetxattr(path, attr, dest) + + for errors.Is(err, unix.ERANGE) { + // Buffer too small, use zero-sized buffer to get the actual size + sz, err = unix.Lgetxattr(path, attr, []byte{}) + if err != nil { + return nil, wrapPathError("lgetxattr", path, attr, err) + } + dest = make([]byte, sz) + sz, err = unix.Lgetxattr(path, attr, dest) + } + + if err != nil { + if errors.Is(err, noattr) { + return nil, nil + } + return nil, wrapPathError("lgetxattr", path, attr, err) + } + + return dest[:sz], nil +} + +// lsetxattr sets the value of the extended attribute identified by attr +// and associated with the given path in the file system. +func lsetxattr(path string, attr string, data []byte, flags int) error { + return wrapPathError("lsetxattr", path, attr, unix.Lsetxattr(path, attr, data, flags)) +} + +func wrapPathError(op, path, attr string, err error) error { + if err == nil { + return nil + } + return &fs.PathError{Op: op, Path: path, Err: fmt.Errorf("xattr %q: %w", attr, err)} +} diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go b/vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go new file mode 100644 index 000000000..f2e76465a --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go @@ -0,0 +1,5 @@ +package archive + +import "golang.org/x/sys/unix" + +var noattr = unix.ENODATA diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go b/vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go new file mode 100644 index 000000000..4d8824158 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go @@ -0,0 +1,7 @@ +//go:build !linux && !windows + +package archive + +import "golang.org/x/sys/unix" + +var noattr = unix.ENOATTR diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go b/vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go new file mode 100644 index 000000000..b0d9165cd --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go @@ -0,0 +1,11 @@ +//go:build !linux && !darwin && !freebsd && !netbsd + +package archive + +func lgetxattr(path string, attr string) ([]byte, error) { + return nil, nil +} + +func lsetxattr(path string, attr string, data []byte, flags int) error { + return nil +} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go b/vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go similarity index 74% rename from vendor/github.com/docker/docker/pkg/ioutils/fswriters.go rename to vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go index 05da97b0e..cbbe835bb 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go +++ b/vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go @@ -1,4 +1,4 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" +package atomicwriter import ( "io" @@ -6,11 +6,11 @@ import ( "path/filepath" ) -// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a +// New returns a WriteCloser so that writing to it writes to a // temporary file and closing it atomically changes the temporary file to // destination path. Writing and closing concurrently is not allowed. // NOTE: umask is not considered for the file's permissions. -func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) { +func New(filename string, perm os.FileMode) (io.WriteCloser, error) { f, err := os.CreateTemp(filepath.Dir(filename), ".tmp-"+filepath.Base(filename)) if err != nil { return nil, err @@ -27,10 +27,10 @@ func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, err }, nil } -// AtomicWriteFile atomically writes data to a file named by filename and with the specified permission bits. +// WriteFile atomically writes data to a file named by filename and with the specified permission bits. // NOTE: umask is not considered for the file's permissions. -func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { - f, err := NewAtomicFileWriter(filename, perm) +func WriteFile(filename string, data []byte, perm os.FileMode) error { + f, err := New(filename, perm) if err != nil { return err } @@ -82,32 +82,32 @@ func (w *atomicFileWriter) Close() (retErr error) { return nil } -// AtomicWriteSet is used to atomically write a set +// WriteSet is used to atomically write a set // of files and ensure they are visible at the same time. // Must be committed to a new directory. -type AtomicWriteSet struct { +type WriteSet struct { root string } -// NewAtomicWriteSet creates a new atomic write set to +// NewWriteSet creates a new atomic write set to // atomically create a set of files. The given directory // is used as the base directory for storing files before // commit. If no temporary directory is given the system // default is used. -func NewAtomicWriteSet(tmpDir string) (*AtomicWriteSet, error) { +func NewWriteSet(tmpDir string) (*WriteSet, error) { td, err := os.MkdirTemp(tmpDir, "write-set-") if err != nil { return nil, err } - return &AtomicWriteSet{ + return &WriteSet{ root: td, }, nil } // WriteFile writes a file to the set, guaranteeing the file // has been synced. -func (ws *AtomicWriteSet) WriteFile(filename string, data []byte, perm os.FileMode) error { +func (ws *WriteSet) WriteFile(filename string, data []byte, perm os.FileMode) error { f, err := ws.FileWriter(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) if err != nil { return err @@ -136,7 +136,7 @@ func (w syncFileCloser) Close() error { // FileWriter opens a file writer inside the set. The file // should be synced and closed before calling commit. -func (ws *AtomicWriteSet) FileWriter(name string, flag int, perm os.FileMode) (io.WriteCloser, error) { +func (ws *WriteSet) FileWriter(name string, flag int, perm os.FileMode) (io.WriteCloser, error) { f, err := os.OpenFile(filepath.Join(ws.root, name), flag, perm) if err != nil { return nil, err @@ -146,18 +146,18 @@ func (ws *AtomicWriteSet) FileWriter(name string, flag int, perm os.FileMode) (i // Cancel cancels the set and removes all temporary data // created in the set. -func (ws *AtomicWriteSet) Cancel() error { +func (ws *WriteSet) Cancel() error { return os.RemoveAll(ws.root) } // Commit moves all created files to the target directory. The // target directory must not exist and the parent of the target // directory must exist. -func (ws *AtomicWriteSet) Commit(target string) error { +func (ws *WriteSet) Commit(target string) error { return os.Rename(ws.root, target) } // String returns the location the set is writing to. -func (ws *AtomicWriteSet) String() string { +func (ws *WriteSet) String() string { return ws.root } diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools.go b/vendor/github.com/docker/docker/pkg/idtools/idtools.go index 79d682c69..d2fbd943a 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools.go @@ -1,11 +1,8 @@ -package idtools // import "github.com/docker/docker/pkg/idtools" +package idtools import ( - "bufio" "fmt" "os" - "strconv" - "strings" ) // IDMap contains a single entry for user namespace range remapping. An array @@ -17,22 +14,6 @@ type IDMap struct { Size int `json:"size"` } -type subIDRange struct { - Start int - Length int -} - -type ranges []subIDRange - -func (e ranges) Len() int { return len(e) } -func (e ranges) Swap(i, j int) { e[i], e[j] = e[j], e[i] } -func (e ranges) Less(i, j int) bool { return e[i].Start < e[j].Start } - -const ( - subuidFileName = "/etc/subuid" - subgidFileName = "/etc/subgid" -) - // MkdirAllAndChown creates a directory (include any along the path) and then modifies // ownership to the requested uid/gid. If the directory already exists, this // function will still change ownership and permissions. @@ -162,67 +143,6 @@ func (i IdentityMapping) Empty() bool { return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0 } -func createIDMap(subidRanges ranges) []IDMap { - idMap := []IDMap{} - - containerID := 0 - for _, idrange := range subidRanges { - idMap = append(idMap, IDMap{ - ContainerID: containerID, - HostID: idrange.Start, - Size: idrange.Length, - }) - containerID = containerID + idrange.Length - } - return idMap -} - -func parseSubuid(username string) (ranges, error) { - return parseSubidFile(subuidFileName, username) -} - -func parseSubgid(username string) (ranges, error) { - return parseSubidFile(subgidFileName, username) -} - -// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid) -// and return all found ranges for a specified username. If the special value -// "ALL" is supplied for username, then all ranges in the file will be returned -func parseSubidFile(path, username string) (ranges, error) { - var rangeList ranges - - subidFile, err := os.Open(path) - if err != nil { - return rangeList, err - } - defer subidFile.Close() - - s := bufio.NewScanner(subidFile) - for s.Scan() { - text := strings.TrimSpace(s.Text()) - if text == "" || strings.HasPrefix(text, "#") { - continue - } - parts := strings.Split(text, ":") - if len(parts) != 3 { - return rangeList, fmt.Errorf("Cannot parse subuid/gid information: Format not correct for %s file", path) - } - if parts[0] == username || username == "ALL" { - startid, err := strconv.Atoi(parts[1]) - if err != nil { - return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err) - } - length, err := strconv.Atoi(parts[2]) - if err != nil { - return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err) - } - rangeList = append(rangeList, subIDRange{startid, length}) - } - } - - return rangeList, s.Err() -} - // CurrentIdentity returns the identity of the current process func CurrentIdentity() Identity { return Identity{UID: os.Getuid(), GID: os.Getegid()} diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go index cd621bdcc..1f11fe474 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go @@ -1,13 +1,10 @@ //go:build !windows -package idtools // import "github.com/docker/docker/pkg/idtools" +package idtools import ( - "bytes" "fmt" - "io" "os" - "os/exec" "path/filepath" "strconv" "syscall" @@ -72,127 +69,25 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting return nil } -// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username, -// followed by a call to `getent` for supporting host configured non-files passwd and group dbs +// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username +// +// Deprecated: use [user.LookupUser] instead func LookupUser(name string) (user.User, error) { - // first try a local system files lookup using existing capabilities - usr, err := user.LookupUser(name) - if err == nil { - return usr, nil - } - // local files lookup failed; attempt to call `getent` to query configured passwd dbs - usr, err = getentUser(name) - if err != nil { - return user.User{}, err - } - return usr, nil + return user.LookupUser(name) } -// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid, -// followed by a call to `getent` for supporting host configured non-files passwd and group dbs +// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid +// +// Deprecated: use [user.LookupUid] instead func LookupUID(uid int) (user.User, error) { - // first try a local system files lookup using existing capabilities - usr, err := user.LookupUid(uid) - if err == nil { - return usr, nil - } - // local files lookup failed; attempt to call `getent` to query configured passwd dbs - return getentUser(strconv.Itoa(uid)) -} - -func getentUser(name string) (user.User, error) { - reader, err := callGetent("passwd", name) - if err != nil { - return user.User{}, err - } - users, err := user.ParsePasswd(reader) - if err != nil { - return user.User{}, err - } - if len(users) == 0 { - return user.User{}, fmt.Errorf("getent failed to find passwd entry for %q", name) - } - return users[0], nil + return user.LookupUid(uid) } // LookupGroup uses traditional local system files lookup (from libcontainer/user) on a group name, -// followed by a call to `getent` for supporting host configured non-files passwd and group dbs +// +// Deprecated: use [user.LookupGroup] instead func LookupGroup(name string) (user.Group, error) { - // first try a local system files lookup using existing capabilities - group, err := user.LookupGroup(name) - if err == nil { - return group, nil - } - // local files lookup failed; attempt to call `getent` to query configured group dbs - return getentGroup(name) -} - -// LookupGID uses traditional local system files lookup (from libcontainer/user) on a group ID, -// followed by a call to `getent` for supporting host configured non-files passwd and group dbs -func LookupGID(gid int) (user.Group, error) { - // first try a local system files lookup using existing capabilities - group, err := user.LookupGid(gid) - if err == nil { - return group, nil - } - // local files lookup failed; attempt to call `getent` to query configured group dbs - return getentGroup(strconv.Itoa(gid)) -} - -func getentGroup(name string) (user.Group, error) { - reader, err := callGetent("group", name) - if err != nil { - return user.Group{}, err - } - groups, err := user.ParseGroup(reader) - if err != nil { - return user.Group{}, err - } - if len(groups) == 0 { - return user.Group{}, fmt.Errorf("getent failed to find groups entry for %q", name) - } - return groups[0], nil -} - -func callGetent(database, key string) (io.Reader, error) { - getentCmd, err := resolveBinary("getent") - // if no `getent` command within the execution environment, can't do anything else - if err != nil { - return nil, fmt.Errorf("unable to find getent command: %w", err) - } - command := exec.Command(getentCmd, database, key) - // we run getent within container filesystem, but without /dev so /dev/null is not available for exec to mock stdin - command.Stdin = io.NopCloser(bytes.NewReader(nil)) - out, err := command.CombinedOutput() - if err != nil { - exitCode, errC := getExitCode(err) - if errC != nil { - return nil, err - } - switch exitCode { - case 1: - return nil, fmt.Errorf("getent reported invalid parameters/database unknown") - case 2: - return nil, fmt.Errorf("getent unable to find entry %q in %s database", key, database) - case 3: - return nil, fmt.Errorf("getent database doesn't support enumeration") - default: - return nil, err - } - } - return bytes.NewReader(out), nil -} - -// getExitCode returns the ExitStatus of the specified error if its type is -// exec.ExitError, returns 0 and an error otherwise. -func getExitCode(err error) (int, error) { - exitCode := 0 - if exiterr, ok := err.(*exec.ExitError); ok { - if procExit, ok := exiterr.Sys().(syscall.WaitStatus); ok { - return procExit.ExitStatus(), nil - } - } - return exitCode, fmt.Errorf("failed to get exit code") + return user.LookupGroup(name) } // setPermissions performs a chown/chmod only if the uid/gid don't match what's requested @@ -223,16 +118,17 @@ func setPermissions(p string, mode os.FileMode, owner Identity, stat os.FileInfo // using the data from /etc/sub{uid,gid} ranges, creates the // proper uid and gid remapping ranges for that user/group pair func LoadIdentityMapping(name string) (IdentityMapping, error) { - usr, err := LookupUser(name) + // TODO: Consider adding support for calling out to "getent" + usr, err := user.LookupUser(name) if err != nil { return IdentityMapping{}, fmt.Errorf("could not get user for username %s: %v", name, err) } - subuidRanges, err := lookupSubUIDRanges(usr) + subuidRanges, err := lookupSubRangesFile("/etc/subuid", usr) if err != nil { return IdentityMapping{}, err } - subgidRanges, err := lookupSubGIDRanges(usr) + subgidRanges, err := lookupSubRangesFile("/etc/subgid", usr) if err != nil { return IdentityMapping{}, err } @@ -243,36 +139,28 @@ func LoadIdentityMapping(name string) (IdentityMapping, error) { }, nil } -func lookupSubUIDRanges(usr user.User) ([]IDMap, error) { - rangeList, err := parseSubuid(strconv.Itoa(usr.Uid)) +func lookupSubRangesFile(path string, usr user.User) ([]IDMap, error) { + uidstr := strconv.Itoa(usr.Uid) + rangeList, err := user.ParseSubIDFileFilter(path, func(sid user.SubID) bool { + return sid.Name == usr.Name || sid.Name == uidstr + }) if err != nil { return nil, err } - if len(rangeList) == 0 { - rangeList, err = parseSubuid(usr.Name) - if err != nil { - return nil, err - } - } if len(rangeList) == 0 { return nil, fmt.Errorf("no subuid ranges found for user %q", usr.Name) } - return createIDMap(rangeList), nil -} -func lookupSubGIDRanges(usr user.User) ([]IDMap, error) { - rangeList, err := parseSubgid(strconv.Itoa(usr.Uid)) - if err != nil { - return nil, err - } - if len(rangeList) == 0 { - rangeList, err = parseSubgid(usr.Name) - if err != nil { - return nil, err - } - } - if len(rangeList) == 0 { - return nil, fmt.Errorf("no subgid ranges found for user %q", usr.Name) + idMap := []IDMap{} + + containerID := 0 + for _, idrange := range rangeList { + idMap = append(idMap, IDMap{ + ContainerID: containerID, + HostID: int(idrange.SubID), + Size: int(idrange.Count), + }) + containerID = containerID + int(idrange.Count) } - return createIDMap(rangeList), nil + return idMap, nil } diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go index 32953f456..a12b14040 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go @@ -1,24 +1,24 @@ -package idtools // import "github.com/docker/docker/pkg/idtools" +package idtools import ( "os" - - "github.com/docker/docker/pkg/system" ) const ( SeTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege" ) +// TODO(thaJeztah): these magic consts need a source of reference, and should be defined in a canonical location const ( ContainerAdministratorSidString = "S-1-5-93-2-1" - ContainerUserSidString = "S-1-5-93-2-2" + + ContainerUserSidString = "S-1-5-93-2-2" ) -// This is currently a wrapper around MkdirAll, however, since currently +// This is currently a wrapper around [os.MkdirAll] since currently // permissions aren't set through this path, the identity isn't utilized. // Ownership is handled elsewhere, but in the future could be support here // too. func mkdirAs(path string, _ os.FileMode, _ Identity, _, _ bool) error { - return system.MkdirAll(path, 0) + return os.MkdirAll(path, 0) } diff --git a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go deleted file mode 100644 index f0c075e20..000000000 --- a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go +++ /dev/null @@ -1,166 +0,0 @@ -package idtools // import "github.com/docker/docker/pkg/idtools" - -import ( - "fmt" - "os/exec" - "regexp" - "sort" - "strconv" - "strings" - "sync" -) - -// add a user and/or group to Linux /etc/passwd, /etc/group using standard -// Linux distribution commands: -// adduser --system --shell /bin/false --disabled-login --disabled-password --no-create-home --group -// useradd -r -s /bin/false - -var ( - once sync.Once - userCommand string - idOutRegexp = regexp.MustCompile(`uid=([0-9]+).*gid=([0-9]+)`) -) - -const ( - // default length for a UID/GID subordinate range - defaultRangeLen = 65536 - defaultRangeStart = 100000 -) - -// AddNamespaceRangesUser takes a username and uses the standard system -// utility to create a system user/group pair used to hold the -// /etc/sub{uid,gid} ranges which will be used for user namespace -// mapping ranges in containers. -func AddNamespaceRangesUser(name string) (int, int, error) { - if err := addUser(name); err != nil { - return -1, -1, fmt.Errorf("error adding user %q: %v", name, err) - } - - // Query the system for the created uid and gid pair - out, err := exec.Command("id", name).CombinedOutput() - if err != nil { - return -1, -1, fmt.Errorf("error trying to find uid/gid for new user %q: %v", name, err) - } - matches := idOutRegexp.FindStringSubmatch(strings.TrimSpace(string(out))) - if len(matches) != 3 { - return -1, -1, fmt.Errorf("can't find uid, gid from `id` output: %q", string(out)) - } - uid, err := strconv.Atoi(matches[1]) - if err != nil { - return -1, -1, fmt.Errorf("can't convert found uid (%s) to int: %v", matches[1], err) - } - gid, err := strconv.Atoi(matches[2]) - if err != nil { - return -1, -1, fmt.Errorf("Can't convert found gid (%s) to int: %v", matches[2], err) - } - - // Now we need to create the subuid/subgid ranges for our new user/group (system users - // do not get auto-created ranges in subuid/subgid) - - if err := createSubordinateRanges(name); err != nil { - return -1, -1, fmt.Errorf("couldn't create subordinate ID ranges: %v", err) - } - return uid, gid, nil -} - -func addUser(name string) error { - once.Do(func() { - // set up which commands are used for adding users/groups dependent on distro - if _, err := resolveBinary("adduser"); err == nil { - userCommand = "adduser" - } else if _, err := resolveBinary("useradd"); err == nil { - userCommand = "useradd" - } - }) - var args []string - switch userCommand { - case "adduser": - args = []string{"--system", "--shell", "/bin/false", "--no-create-home", "--disabled-login", "--disabled-password", "--group", name} - case "useradd": - args = []string{"-r", "-s", "/bin/false", name} - default: - return fmt.Errorf("cannot add user; no useradd/adduser binary found") - } - - if out, err := exec.Command(userCommand, args...).CombinedOutput(); err != nil { - return fmt.Errorf("failed to add user with error: %v; output: %q", err, string(out)) - } - return nil -} - -func createSubordinateRanges(name string) error { - // first, we should verify that ranges weren't automatically created - // by the distro tooling - ranges, err := parseSubuid(name) - if err != nil { - return fmt.Errorf("error while looking for subuid ranges for user %q: %v", name, err) - } - if len(ranges) == 0 { - // no UID ranges; let's create one - startID, err := findNextUIDRange() - if err != nil { - return fmt.Errorf("can't find available subuid range: %v", err) - } - idRange := fmt.Sprintf("%d-%d", startID, startID+defaultRangeLen-1) - out, err := exec.Command("usermod", "-v", idRange, name).CombinedOutput() - if err != nil { - return fmt.Errorf("unable to add subuid range to user: %q; output: %s, err: %v", name, out, err) - } - } - - ranges, err = parseSubgid(name) - if err != nil { - return fmt.Errorf("error while looking for subgid ranges for user %q: %v", name, err) - } - if len(ranges) == 0 { - // no GID ranges; let's create one - startID, err := findNextGIDRange() - if err != nil { - return fmt.Errorf("can't find available subgid range: %v", err) - } - idRange := fmt.Sprintf("%d-%d", startID, startID+defaultRangeLen-1) - out, err := exec.Command("usermod", "-w", idRange, name).CombinedOutput() - if err != nil { - return fmt.Errorf("unable to add subgid range to user: %q; output: %s, err: %v", name, out, err) - } - } - return nil -} - -func findNextUIDRange() (int, error) { - ranges, err := parseSubuid("ALL") - if err != nil { - return -1, fmt.Errorf("couldn't parse all ranges in /etc/subuid file: %v", err) - } - sort.Sort(ranges) - return findNextRangeStart(ranges) -} - -func findNextGIDRange() (int, error) { - ranges, err := parseSubgid("ALL") - if err != nil { - return -1, fmt.Errorf("couldn't parse all ranges in /etc/subgid file: %v", err) - } - sort.Sort(ranges) - return findNextRangeStart(ranges) -} - -func findNextRangeStart(rangeList ranges) (int, error) { - startID := defaultRangeStart - for _, arange := range rangeList { - if wouldOverlap(arange, startID) { - startID = arange.Start + arange.Length - } - } - return startID, nil -} - -func wouldOverlap(arange subIDRange, ID int) bool { - low := ID - high := ID + defaultRangeLen - if (low >= arange.Start && low <= arange.Start+arange.Length) || - (high <= arange.Start+arange.Length && high >= arange.Start) { - return true - } - return false -} diff --git a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go deleted file mode 100644 index 6a9311c4a..000000000 --- a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !linux - -package idtools // import "github.com/docker/docker/pkg/idtools" - -import "fmt" - -// AddNamespaceRangesUser takes a name and finds an unused uid, gid pair -// and calls the appropriate helper function to add the group and then -// the user to the group in /etc/group and /etc/passwd respectively. -func AddNamespaceRangesUser(name string) (int, int, error) { - return -1, -1, fmt.Errorf("No support for adding users or groups on this OS") -} diff --git a/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go b/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go deleted file mode 100644 index 517a2f52c..000000000 --- a/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build !windows - -package idtools // import "github.com/docker/docker/pkg/idtools" - -import ( - "fmt" - "os/exec" - "path/filepath" -) - -func resolveBinary(binname string) (string, error) { - binaryPath, err := exec.LookPath(binname) - if err != nil { - return "", err - } - resolvedPath, err := filepath.EvalSymlinks(binaryPath) - if err != nil { - return "", err - } - // only return no error if the final resolved binary basename - // matches what was searched for - if filepath.Base(resolvedPath) == binname { - return resolvedPath, nil - } - return "", fmt.Errorf("Binary %q does not resolve to a binary of that name in $PATH (%q)", binname, resolvedPath) -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go b/vendor/github.com/docker/docker/pkg/ioutils/buffer.go deleted file mode 100644 index 466f79294..000000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go +++ /dev/null @@ -1,51 +0,0 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" - -import ( - "errors" - "io" -) - -var errBufferFull = errors.New("buffer is full") - -type fixedBuffer struct { - buf []byte - pos int - lastRead int -} - -func (b *fixedBuffer) Write(p []byte) (int, error) { - n := copy(b.buf[b.pos:cap(b.buf)], p) - b.pos += n - - if n < len(p) { - if b.pos == cap(b.buf) { - return n, errBufferFull - } - return n, io.ErrShortWrite - } - return n, nil -} - -func (b *fixedBuffer) Read(p []byte) (int, error) { - n := copy(p, b.buf[b.lastRead:b.pos]) - b.lastRead += n - return n, nil -} - -func (b *fixedBuffer) Len() int { - return b.pos - b.lastRead -} - -func (b *fixedBuffer) Cap() int { - return cap(b.buf) -} - -func (b *fixedBuffer) Reset() { - b.pos = 0 - b.lastRead = 0 - b.buf = b.buf[:0] -} - -func (b *fixedBuffer) String() string { - return string(b.buf[b.lastRead:b.pos]) -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go deleted file mode 100644 index c1cfa62fd..000000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go +++ /dev/null @@ -1,187 +0,0 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" - -import ( - "errors" - "io" - "sync" -) - -// maxCap is the highest capacity to use in byte slices that buffer data. -const maxCap = 1e6 - -// minCap is the lowest capacity to use in byte slices that buffer data -const minCap = 64 - -// blockThreshold is the minimum number of bytes in the buffer which will cause -// a write to BytesPipe to block when allocating a new slice. -const blockThreshold = 1e6 - -var ( - // ErrClosed is returned when Write is called on a closed BytesPipe. - ErrClosed = errors.New("write to closed BytesPipe") - - bufPools = make(map[int]*sync.Pool) - bufPoolsLock sync.Mutex -) - -// BytesPipe is io.ReadWriteCloser which works similarly to pipe(queue). -// All written data may be read at most once. Also, BytesPipe allocates -// and releases new byte slices to adjust to current needs, so the buffer -// won't be overgrown after peak loads. -type BytesPipe struct { - mu sync.Mutex - wait *sync.Cond - buf []*fixedBuffer - bufLen int - closeErr error // error to return from next Read. set to nil if not closed. - readBlock bool // check read BytesPipe is Wait() or not -} - -// NewBytesPipe creates new BytesPipe, initialized by specified slice. -// If buf is nil, then it will be initialized with slice which cap is 64. -// buf will be adjusted in a way that len(buf) == 0, cap(buf) == cap(buf). -func NewBytesPipe() *BytesPipe { - bp := &BytesPipe{} - bp.buf = append(bp.buf, getBuffer(minCap)) - bp.wait = sync.NewCond(&bp.mu) - return bp -} - -// Write writes p to BytesPipe. -// It can allocate new []byte slices in a process of writing. -func (bp *BytesPipe) Write(p []byte) (int, error) { - bp.mu.Lock() - defer bp.mu.Unlock() - - written := 0 -loop0: - for { - if bp.closeErr != nil { - return written, ErrClosed - } - - if len(bp.buf) == 0 { - bp.buf = append(bp.buf, getBuffer(64)) - } - // get the last buffer - b := bp.buf[len(bp.buf)-1] - - n, err := b.Write(p) - written += n - bp.bufLen += n - - // errBufferFull is an error we expect to get if the buffer is full - if err != nil && err != errBufferFull { - bp.wait.Broadcast() - return written, err - } - - // if there was enough room to write all then break - if len(p) == n { - break - } - - // more data: write to the next slice - p = p[n:] - - // make sure the buffer doesn't grow too big from this write - for bp.bufLen >= blockThreshold { - if bp.readBlock { - bp.wait.Broadcast() - } - bp.wait.Wait() - if bp.closeErr != nil { - continue loop0 - } - } - - // add new byte slice to the buffers slice and continue writing - nextCap := b.Cap() * 2 - if nextCap > maxCap { - nextCap = maxCap - } - bp.buf = append(bp.buf, getBuffer(nextCap)) - } - bp.wait.Broadcast() - return written, nil -} - -// CloseWithError causes further reads from a BytesPipe to return immediately. -func (bp *BytesPipe) CloseWithError(err error) error { - bp.mu.Lock() - if err != nil { - bp.closeErr = err - } else { - bp.closeErr = io.EOF - } - bp.wait.Broadcast() - bp.mu.Unlock() - return nil -} - -// Close causes further reads from a BytesPipe to return immediately. -func (bp *BytesPipe) Close() error { - return bp.CloseWithError(nil) -} - -// Read reads bytes from BytesPipe. -// Data could be read only once. -func (bp *BytesPipe) Read(p []byte) (n int, err error) { - bp.mu.Lock() - defer bp.mu.Unlock() - if bp.bufLen == 0 { - if bp.closeErr != nil { - return 0, bp.closeErr - } - bp.readBlock = true - bp.wait.Wait() - bp.readBlock = false - if bp.bufLen == 0 && bp.closeErr != nil { - return 0, bp.closeErr - } - } - - for bp.bufLen > 0 { - b := bp.buf[0] - read, _ := b.Read(p) // ignore error since fixedBuffer doesn't really return an error - n += read - bp.bufLen -= read - - if b.Len() == 0 { - // it's empty so return it to the pool and move to the next one - returnBuffer(b) - bp.buf[0] = nil - bp.buf = bp.buf[1:] - } - - if len(p) == read { - break - } - - p = p[read:] - } - - bp.wait.Broadcast() - return -} - -func returnBuffer(b *fixedBuffer) { - b.Reset() - bufPoolsLock.Lock() - pool := bufPools[b.Cap()] - bufPoolsLock.Unlock() - if pool != nil { - pool.Put(b) - } -} - -func getBuffer(size int) *fixedBuffer { - bufPoolsLock.Lock() - pool, ok := bufPools[size] - if !ok { - pool = &sync.Pool{New: func() interface{} { return &fixedBuffer{buf: make([]byte, 0, size)} }} - bufPools[size] = pool - } - bufPoolsLock.Unlock() - return pool.Get().(*fixedBuffer) -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go new file mode 100644 index 000000000..c3cee16db --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go @@ -0,0 +1,44 @@ +package ioutils + +import ( + "io" + "os" + + "github.com/docker/docker/pkg/atomicwriter" +) + +// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a +// temporary file and closing it atomically changes the temporary file to +// destination path. Writing and closing concurrently is not allowed. +// NOTE: umask is not considered for the file's permissions. +// +// Deprecated: use [atomicwriter.New] instead. +func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) { + return atomicwriter.New(filename, perm) +} + +// AtomicWriteFile atomically writes data to a file named by filename and with the specified permission bits. +// NOTE: umask is not considered for the file's permissions. +// +// Deprecated: use [atomicwriter.WriteFile] instead. +func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { + return atomicwriter.WriteFile(filename, data, perm) +} + +// AtomicWriteSet is used to atomically write a set +// of files and ensure they are visible at the same time. +// Must be committed to a new directory. +// +// Deprecated: use [atomicwriter.WriteSet] instead. +type AtomicWriteSet = atomicwriter.WriteSet + +// NewAtomicWriteSet creates a new atomic write set to +// atomically create a set of files. The given directory +// is used as the base directory for storing files before +// commit. If no temporary directory is given the system +// default is used. +// +// Deprecated: use [atomicwriter.NewWriteSet] instead. +func NewAtomicWriteSet(tmpDir string) (*atomicwriter.WriteSet, error) { + return atomicwriter.NewWriteSet(tmpDir) +} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/readers.go b/vendor/github.com/docker/docker/pkg/ioutils/readers.go index e03d3fee7..9ddba2468 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/readers.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/readers.go @@ -6,25 +6,20 @@ import ( "runtime/debug" "sync/atomic" - // make sure crypto.SHA256, crypto.sha512 and crypto.SHA384 are registered - // TODO remove once https://github.com/opencontainers/go-digest/pull/64 is merged. - _ "crypto/sha256" - _ "crypto/sha512" - "github.com/containerd/log" ) -// ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser +// readCloserWrapper wraps an io.Reader, and implements an io.ReadCloser // It calls the given callback function when closed. It should be constructed // with NewReadCloserWrapper -type ReadCloserWrapper struct { +type readCloserWrapper struct { io.Reader closer func() error closed atomic.Bool } // Close calls back the passed closer function -func (r *ReadCloserWrapper) Close() error { +func (r *readCloserWrapper) Close() error { if !r.closed.CompareAndSwap(false, true) { subsequentCloseWarn("ReadCloserWrapper") return nil @@ -32,64 +27,15 @@ func (r *ReadCloserWrapper) Close() error { return r.closer() } -// NewReadCloserWrapper returns a new io.ReadCloser. +// NewReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser. +// It calls the given callback function when closed. func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { - return &ReadCloserWrapper{ + return &readCloserWrapper{ Reader: r, closer: closer, } } -type readerErrWrapper struct { - reader io.Reader - closer func() -} - -func (r *readerErrWrapper) Read(p []byte) (int, error) { - n, err := r.reader.Read(p) - if err != nil { - r.closer() - } - return n, err -} - -// NewReaderErrWrapper returns a new io.Reader. -func NewReaderErrWrapper(r io.Reader, closer func()) io.Reader { - return &readerErrWrapper{ - reader: r, - closer: closer, - } -} - -// OnEOFReader wraps an io.ReadCloser and a function -// the function will run at the end of file or close the file. -type OnEOFReader struct { - Rc io.ReadCloser - Fn func() -} - -func (r *OnEOFReader) Read(p []byte) (n int, err error) { - n, err = r.Rc.Read(p) - if err == io.EOF { - r.runFunc() - } - return -} - -// Close closes the file and run the function. -func (r *OnEOFReader) Close() error { - err := r.Rc.Close() - r.runFunc() - return err -} - -func (r *OnEOFReader) runFunc() { - if fn := r.Fn; fn != nil { - fn() - r.Fn = nil - } -} - // cancelReadCloser wraps an io.ReadCloser with a context for cancelling read // operations. type cancelReadCloser struct { diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go index 91b8d1826..010db59fe 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go @@ -21,12 +21,10 @@ type flusher interface { Flush() } -var errWriteFlusherClosed = io.EOF - func (wf *WriteFlusher) Write(b []byte) (n int, err error) { select { case <-wf.closed: - return 0, errWriteFlusherClosed + return 0, io.EOF default: } @@ -73,20 +71,26 @@ func (wf *WriteFlusher) Close() error { select { case <-wf.closed: - return errWriteFlusherClosed + return io.EOF default: close(wf.closed) } return nil } +// nopFlusher represents a type which flush operation is nop. +type nopFlusher struct{} + +// Flush is a nop operation. +func (f *nopFlusher) Flush() {} + // NewWriteFlusher returns a new WriteFlusher. func NewWriteFlusher(w io.Writer) *WriteFlusher { var fl flusher if f, ok := w.(flusher); ok { fl = f } else { - fl = &NopFlusher{} + fl = &nopFlusher{} } return &WriteFlusher{w: w, flusher: fl, closed: make(chan struct{}), flushed: make(chan struct{})} } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writers.go b/vendor/github.com/docker/docker/pkg/ioutils/writers.go index 1f50602f2..9c2d5d3b7 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/writers.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/writers.go @@ -5,30 +5,6 @@ import ( "sync/atomic" ) -// NopWriter represents a type which write operation is nop. -type NopWriter struct{} - -func (*NopWriter) Write(buf []byte) (int, error) { - return len(buf), nil -} - -type nopWriteCloser struct { - io.Writer -} - -func (w *nopWriteCloser) Close() error { return nil } - -// NopWriteCloser returns a nopWriteCloser. -func NopWriteCloser(w io.Writer) io.WriteCloser { - return &nopWriteCloser{w} -} - -// NopFlusher represents a type which flush operation is nop. -type NopFlusher struct{} - -// Flush is a nop operation. -func (f *NopFlusher) Flush() {} - type writeCloserWrapper struct { io.Writer closer func() error @@ -50,25 +26,3 @@ func NewWriteCloserWrapper(r io.Writer, closer func() error) io.WriteCloser { closer: closer, } } - -// WriteCounter wraps a concrete io.Writer and hold a count of the number -// of bytes written to the writer during a "session". -// This can be convenient when write return is masked -// (e.g., json.Encoder.Encode()) -type WriteCounter struct { - Count int64 - Writer io.Writer -} - -// NewWriteCounter returns a new WriteCounter. -func NewWriteCounter(w io.Writer) *WriteCounter { - return &WriteCounter{ - Writer: w, - } -} - -func (wc *WriteCounter) Write(p []byte) (count int, err error) { - count, err = wc.Writer.Write(p) - wc.Count += int64(count) - return -} diff --git a/vendor/github.com/docker/docker/pkg/pools/pools.go b/vendor/github.com/docker/docker/pkg/pools/pools.go deleted file mode 100644 index 3792c67a9..000000000 --- a/vendor/github.com/docker/docker/pkg/pools/pools.go +++ /dev/null @@ -1,137 +0,0 @@ -// Package pools provides a collection of pools which provide various -// data types with buffers. These can be used to lower the number of -// memory allocations and reuse buffers. -// -// New pools should be added to this package to allow them to be -// shared across packages. -// -// Utility functions which operate on pools should be added to this -// package to allow them to be reused. -package pools // import "github.com/docker/docker/pkg/pools" - -import ( - "bufio" - "io" - "sync" - - "github.com/docker/docker/pkg/ioutils" -) - -const buffer32K = 32 * 1024 - -var ( - // BufioReader32KPool is a pool which returns bufio.Reader with a 32K buffer. - BufioReader32KPool = newBufioReaderPoolWithSize(buffer32K) - // BufioWriter32KPool is a pool which returns bufio.Writer with a 32K buffer. - BufioWriter32KPool = newBufioWriterPoolWithSize(buffer32K) - buffer32KPool = newBufferPoolWithSize(buffer32K) -) - -// BufioReaderPool is a bufio reader that uses sync.Pool. -type BufioReaderPool struct { - pool sync.Pool -} - -// newBufioReaderPoolWithSize is unexported because new pools should be -// added here to be shared where required. -func newBufioReaderPoolWithSize(size int) *BufioReaderPool { - return &BufioReaderPool{ - pool: sync.Pool{ - New: func() interface{} { return bufio.NewReaderSize(nil, size) }, - }, - } -} - -// Get returns a bufio.Reader which reads from r. The buffer size is that of the pool. -func (bufPool *BufioReaderPool) Get(r io.Reader) *bufio.Reader { - buf := bufPool.pool.Get().(*bufio.Reader) - buf.Reset(r) - return buf -} - -// Put puts the bufio.Reader back into the pool. -func (bufPool *BufioReaderPool) Put(b *bufio.Reader) { - b.Reset(nil) - bufPool.pool.Put(b) -} - -type bufferPool struct { - pool sync.Pool -} - -func newBufferPoolWithSize(size int) *bufferPool { - return &bufferPool{ - pool: sync.Pool{ - New: func() interface{} { s := make([]byte, size); return &s }, - }, - } -} - -func (bp *bufferPool) Get() *[]byte { - return bp.pool.Get().(*[]byte) -} - -func (bp *bufferPool) Put(b *[]byte) { - bp.pool.Put(b) -} - -// Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy. -func Copy(dst io.Writer, src io.Reader) (written int64, err error) { - buf := buffer32KPool.Get() - written, err = io.CopyBuffer(dst, src, *buf) - buffer32KPool.Put(buf) - return -} - -// NewReadCloserWrapper returns a wrapper which puts the bufio.Reader back -// into the pool and closes the reader if it's an io.ReadCloser. -func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Reader) io.ReadCloser { - return ioutils.NewReadCloserWrapper(r, func() error { - if readCloser, ok := r.(io.ReadCloser); ok { - readCloser.Close() - } - bufPool.Put(buf) - return nil - }) -} - -// BufioWriterPool is a bufio writer that uses sync.Pool. -type BufioWriterPool struct { - pool sync.Pool -} - -// newBufioWriterPoolWithSize is unexported because new pools should be -// added here to be shared where required. -func newBufioWriterPoolWithSize(size int) *BufioWriterPool { - return &BufioWriterPool{ - pool: sync.Pool{ - New: func() interface{} { return bufio.NewWriterSize(nil, size) }, - }, - } -} - -// Get returns a bufio.Writer which writes to w. The buffer size is that of the pool. -func (bufPool *BufioWriterPool) Get(w io.Writer) *bufio.Writer { - buf := bufPool.pool.Get().(*bufio.Writer) - buf.Reset(w) - return buf -} - -// Put puts the bufio.Writer back into the pool. -func (bufPool *BufioWriterPool) Put(b *bufio.Writer) { - b.Reset(nil) - bufPool.pool.Put(b) -} - -// NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back -// into the pool and closes the writer if it's an io.Writecloser. -func (bufPool *BufioWriterPool) NewWriteCloserWrapper(buf *bufio.Writer, w io.Writer) io.WriteCloser { - return ioutils.NewWriteCloserWrapper(w, func() error { - buf.Flush() - if writeCloser, ok := w.(io.WriteCloser); ok { - writeCloser.Close() - } - bufPool.Put(buf) - return nil - }) -} diff --git a/vendor/github.com/docker/docker/pkg/system/args_windows.go b/vendor/github.com/docker/docker/pkg/system/args_windows.go deleted file mode 100644 index b7c9487a0..000000000 --- a/vendor/github.com/docker/docker/pkg/system/args_windows.go +++ /dev/null @@ -1,16 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import ( - "strings" - - "golang.org/x/sys/windows" -) - -// EscapeArgs makes a Windows-style escaped command line from a set of arguments -func EscapeArgs(args []string) string { - escapedArgs := make([]string, len(args)) - for i, a := range args { - escapedArgs[i] = windows.EscapeArg(a) - } - return strings.Join(escapedArgs, " ") -} diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes.go b/vendor/github.com/docker/docker/pkg/system/chtimes.go deleted file mode 100644 index 6a6bca43e..000000000 --- a/vendor/github.com/docker/docker/pkg/system/chtimes.go +++ /dev/null @@ -1,48 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import ( - "os" - "syscall" - "time" - "unsafe" -) - -// Used by Chtimes -var unixEpochTime, unixMaxTime time.Time - -func init() { - unixEpochTime = time.Unix(0, 0) - if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 { - // This is a 64 bit timespec - // os.Chtimes limits time to the following - // - // Note that this intentionally sets nsec (not sec), which sets both sec - // and nsec internally in time.Unix(); - // https://github.com/golang/go/blob/go1.19.2/src/time/time.go#L1364-L1380 - unixMaxTime = time.Unix(0, 1<<63-1) - } else { - // This is a 32 bit timespec - unixMaxTime = time.Unix(1<<31-1, 0) - } -} - -// Chtimes changes the access time and modified time of a file at the given path. -// If the modified time is prior to the Unix Epoch (unixMinTime), or after the -// end of Unix Time (unixEpochTime), os.Chtimes has undefined behavior. In this -// case, Chtimes defaults to Unix Epoch, just in case. -func Chtimes(name string, atime time.Time, mtime time.Time) error { - if atime.Before(unixEpochTime) || atime.After(unixMaxTime) { - atime = unixEpochTime - } - - if mtime.Before(unixEpochTime) || mtime.After(unixMaxTime) { - mtime = unixEpochTime - } - - if err := os.Chtimes(name, atime, mtime); err != nil { - return err - } - - // Take platform specific action for setting create time. - return setCTime(name, mtime) -} diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_nowindows.go b/vendor/github.com/docker/docker/pkg/system/chtimes_nowindows.go deleted file mode 100644 index 92ff02097..000000000 --- a/vendor/github.com/docker/docker/pkg/system/chtimes_nowindows.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build !windows - -package system // import "github.com/docker/docker/pkg/system" - -import ( - "time" -) - -// setCTime will set the create time on a file. On Unix, the create -// time is updated as a side effect of setting the modified time, so -// no action is required. -func setCTime(path string, ctime time.Time) error { - return nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/errors.go b/vendor/github.com/docker/docker/pkg/system/errors.go deleted file mode 100644 index f4bbcce74..000000000 --- a/vendor/github.com/docker/docker/pkg/system/errors.go +++ /dev/null @@ -1,6 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import "errors" - -// ErrNotSupportedPlatform means the platform is not supported. -var ErrNotSupportedPlatform = errors.New("platform and architecture is not supported") diff --git a/vendor/github.com/docker/docker/pkg/system/filesys.go b/vendor/github.com/docker/docker/pkg/system/filesys.go deleted file mode 100644 index ce5990c91..000000000 --- a/vendor/github.com/docker/docker/pkg/system/filesys.go +++ /dev/null @@ -1,19 +0,0 @@ -package system - -import ( - "os" - "path/filepath" - "strings" -) - -// IsAbs is a platform-agnostic wrapper for filepath.IsAbs. -// -// On Windows, golang filepath.IsAbs does not consider a path \windows\system32 -// as absolute as it doesn't start with a drive-letter/colon combination. However, -// in docker we need to verify things such as WORKDIR /windows/system32 in -// a Dockerfile (which gets translated to \windows\system32 when being processed -// by the daemon). This SHOULD be treated as absolute from a docker processing -// perspective. -func IsAbs(path string) bool { - return filepath.IsAbs(path) || strings.HasPrefix(path, string(os.PathSeparator)) -} diff --git a/vendor/github.com/docker/docker/pkg/system/filesys_unix.go b/vendor/github.com/docker/docker/pkg/system/filesys_unix.go deleted file mode 100644 index f01f9385e..000000000 --- a/vendor/github.com/docker/docker/pkg/system/filesys_unix.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !windows - -package system // import "github.com/docker/docker/pkg/system" - -import "os" - -// MkdirAllWithACL is a wrapper for os.MkdirAll on unix systems. -func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error { - return os.MkdirAll(path, perm) -} - -// MkdirAll creates a directory named path along with any necessary parents, -// with permission specified by attribute perm for all dir created. -func MkdirAll(path string, perm os.FileMode) error { - return os.MkdirAll(path, perm) -} diff --git a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go b/vendor/github.com/docker/docker/pkg/system/filesys_windows.go deleted file mode 100644 index 92e972ea2..000000000 --- a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go +++ /dev/null @@ -1,135 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import ( - "os" - "regexp" - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -// SddlAdministratorsLocalSystem is local administrators plus NT AUTHORITY\System. -const SddlAdministratorsLocalSystem = "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)" - -// volumePath is a regular expression to check if a path is a Windows -// volume path (e.g., "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}" -// or "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\"). -var volumePath = regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}\\?$`) - -// MkdirAllWithACL is a custom version of os.MkdirAll modified for use on Windows -// so that it is both volume path aware, and can create a directory with -// an appropriate SDDL defined ACL. -func MkdirAllWithACL(path string, _ os.FileMode, sddl string) error { - sa, err := makeSecurityAttributes(sddl) - if err != nil { - return &os.PathError{Op: "mkdirall", Path: path, Err: err} - } - return mkdirall(path, sa) -} - -// MkdirAll is a custom version of os.MkdirAll that is volume path aware for -// Windows. It can be used as a drop-in replacement for os.MkdirAll. -func MkdirAll(path string, _ os.FileMode) error { - return mkdirall(path, nil) -} - -// mkdirall is a custom version of os.MkdirAll modified for use on Windows -// so that it is both volume path aware, and can create a directory with -// a DACL. -func mkdirall(path string, perm *windows.SecurityAttributes) error { - if volumePath.MatchString(path) { - return nil - } - - // The rest of this method is largely copied from os.MkdirAll and should be kept - // as-is to ensure compatibility. - - // Fast path: if we can tell whether path is a directory or file, stop with success or error. - dir, err := os.Stat(path) - if err == nil { - if dir.IsDir() { - return nil - } - return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} - } - - // Slow path: make sure parent exists and then call Mkdir for path. - i := len(path) - for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator. - i-- - } - - j := i - for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element. - j-- - } - - if j > 1 { - // Create parent. - err = mkdirall(fixRootDirectory(path[:j-1]), perm) - if err != nil { - return err - } - } - - // Parent now exists; invoke Mkdir and use its result. - err = mkdirWithACL(path, perm) - if err != nil { - // Handle arguments like "foo/." by - // double-checking that directory doesn't exist. - dir, err1 := os.Lstat(path) - if err1 == nil && dir.IsDir() { - return nil - } - return err - } - return nil -} - -// mkdirWithACL creates a new directory. If there is an error, it will be of -// type *PathError. . -// -// This is a modified and combined version of os.Mkdir and windows.Mkdir -// in golang to cater for creating a directory am ACL permitting full -// access, with inheritance, to any subfolder/file for Built-in Administrators -// and Local System. -func mkdirWithACL(name string, sa *windows.SecurityAttributes) error { - if sa == nil { - return os.Mkdir(name, 0) - } - - namep, err := windows.UTF16PtrFromString(name) - if err != nil { - return &os.PathError{Op: "mkdir", Path: name, Err: err} - } - - err = windows.CreateDirectory(namep, sa) - if err != nil { - return &os.PathError{Op: "mkdir", Path: name, Err: err} - } - return nil -} - -// fixRootDirectory fixes a reference to a drive's root directory to -// have the required trailing slash. -func fixRootDirectory(p string) string { - if len(p) == len(`\\?\c:`) { - if os.IsPathSeparator(p[0]) && os.IsPathSeparator(p[1]) && p[2] == '?' && os.IsPathSeparator(p[3]) && p[5] == ':' { - return p + `\` - } - } - return p -} - -func makeSecurityAttributes(sddl string) (*windows.SecurityAttributes, error) { - var sa windows.SecurityAttributes - sa.Length = uint32(unsafe.Sizeof(sa)) - sa.InheritHandle = 1 - var err error - sa.SecurityDescriptor, err = windows.SecurityDescriptorFromString(sddl) - if err != nil { - return nil, err - } - return &sa, nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/init_windows.go b/vendor/github.com/docker/docker/pkg/system/init_windows.go deleted file mode 100644 index 7603efbbd..000000000 --- a/vendor/github.com/docker/docker/pkg/system/init_windows.go +++ /dev/null @@ -1,16 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -// containerdRuntimeSupported determines if containerd should be the runtime. -var containerdRuntimeSupported = false - -// InitContainerdRuntime sets whether to use containerd for runtime on Windows. -func InitContainerdRuntime(cdPath string) { - if len(cdPath) > 0 { - containerdRuntimeSupported = true - } -} - -// ContainerdRuntimeSupported returns true if the use of containerd runtime is supported. -func ContainerdRuntimeSupported() bool { - return containerdRuntimeSupported -} diff --git a/vendor/github.com/docker/docker/pkg/system/lstat_unix.go b/vendor/github.com/docker/docker/pkg/system/lstat_unix.go deleted file mode 100644 index 5e29a6b3b..000000000 --- a/vendor/github.com/docker/docker/pkg/system/lstat_unix.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build !windows - -package system // import "github.com/docker/docker/pkg/system" - -import ( - "os" - "syscall" -) - -// Lstat takes a path to a file and returns -// a system.StatT type pertaining to that file. -// -// Throws an error if the file does not exist -func Lstat(path string) (*StatT, error) { - s := &syscall.Stat_t{} - if err := syscall.Lstat(path, s); err != nil { - return nil, &os.PathError{Op: "Lstat", Path: path, Err: err} - } - return fromStatT(s) -} diff --git a/vendor/github.com/docker/docker/pkg/system/lstat_windows.go b/vendor/github.com/docker/docker/pkg/system/lstat_windows.go deleted file mode 100644 index 359c791d9..000000000 --- a/vendor/github.com/docker/docker/pkg/system/lstat_windows.go +++ /dev/null @@ -1,14 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import "os" - -// Lstat calls os.Lstat to get a fileinfo interface back. -// This is then copied into our own locally defined structure. -func Lstat(path string) (*StatT, error) { - fi, err := os.Lstat(path) - if err != nil { - return nil, err - } - - return fromStatT(&fi) -} diff --git a/vendor/github.com/docker/docker/pkg/system/mknod.go b/vendor/github.com/docker/docker/pkg/system/mknod.go deleted file mode 100644 index 2a62237a4..000000000 --- a/vendor/github.com/docker/docker/pkg/system/mknod.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !windows - -package system // import "github.com/docker/docker/pkg/system" - -import ( - "golang.org/x/sys/unix" -) - -// Mkdev is used to build the value of linux devices (in /dev/) which specifies major -// and minor number of the newly created device special file. -// Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes. -// They are, from low to high: the lower 8 bits of the minor, then 12 bits of the major, -// then the top 12 bits of the minor. -func Mkdev(major int64, minor int64) uint32 { - return uint32(unix.Mkdev(uint32(major), uint32(minor))) -} diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go b/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go deleted file mode 100644 index e218e742d..000000000 --- a/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build freebsd - -package system // import "github.com/docker/docker/pkg/system" - -import ( - "golang.org/x/sys/unix" -) - -// Mknod creates a filesystem node (file, device special file or named pipe) named path -// with attributes specified by mode and dev. -func Mknod(path string, mode uint32, dev int) error { - return unix.Mknod(path, mode, uint64(dev)) -} diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_unix.go b/vendor/github.com/docker/docker/pkg/system/mknod_unix.go deleted file mode 100644 index 34df0b923..000000000 --- a/vendor/github.com/docker/docker/pkg/system/mknod_unix.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !freebsd && !windows - -package system // import "github.com/docker/docker/pkg/system" - -import ( - "golang.org/x/sys/unix" -) - -// Mknod creates a filesystem node (file, device special file or named pipe) named path -// with attributes specified by mode and dev. -func Mknod(path string, mode uint32, dev int) error { - return unix.Mknod(path, mode, dev) -} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_bsd.go b/vendor/github.com/docker/docker/pkg/system/stat_bsd.go deleted file mode 100644 index 435b776ee..000000000 --- a/vendor/github.com/docker/docker/pkg/system/stat_bsd.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build freebsd || netbsd - -package system // import "github.com/docker/docker/pkg/system" - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{ - size: s.Size, - mode: uint32(s.Mode), - uid: s.Uid, - gid: s.Gid, - rdev: uint64(s.Rdev), - mtim: s.Mtimespec, - }, nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_darwin.go b/vendor/github.com/docker/docker/pkg/system/stat_darwin.go deleted file mode 100644 index e0b629df0..000000000 --- a/vendor/github.com/docker/docker/pkg/system/stat_darwin.go +++ /dev/null @@ -1,15 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{ - size: s.Size, - mode: uint32(s.Mode), - uid: s.Uid, - gid: s.Gid, - rdev: uint64(s.Rdev), - mtim: s.Mtimespec, - }, nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_illumos.go b/vendor/github.com/docker/docker/pkg/system/stat_illumos.go deleted file mode 100644 index 851374e5d..000000000 --- a/vendor/github.com/docker/docker/pkg/system/stat_illumos.go +++ /dev/null @@ -1,15 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{ - size: s.Size, - mode: uint32(s.Mode), - uid: s.Uid, - gid: s.Gid, - rdev: uint64(s.Rdev), - mtim: s.Mtim, - }, nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_linux.go b/vendor/github.com/docker/docker/pkg/system/stat_linux.go deleted file mode 100644 index 4309d42b9..000000000 --- a/vendor/github.com/docker/docker/pkg/system/stat_linux.go +++ /dev/null @@ -1,22 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{ - size: s.Size, - mode: s.Mode, - uid: s.Uid, - gid: s.Gid, - // the type is 32bit on mips - rdev: uint64(s.Rdev), //nolint: unconvert - mtim: s.Mtim, - }, nil -} - -// FromStatT converts a syscall.Stat_t type to a system.Stat_t type -// This is exposed on Linux as pkg/archive/changes uses it. -func FromStatT(s *syscall.Stat_t) (*StatT, error) { - return fromStatT(s) -} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go b/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go deleted file mode 100644 index 851374e5d..000000000 --- a/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go +++ /dev/null @@ -1,15 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import "syscall" - -// fromStatT converts a syscall.Stat_t type to a system.Stat_t type -func fromStatT(s *syscall.Stat_t) (*StatT, error) { - return &StatT{ - size: s.Size, - mode: uint32(s.Mode), - uid: s.Uid, - gid: s.Gid, - rdev: uint64(s.Rdev), - mtim: s.Mtim, - }, nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_unix.go b/vendor/github.com/docker/docker/pkg/system/stat_unix.go deleted file mode 100644 index 205e54677..000000000 --- a/vendor/github.com/docker/docker/pkg/system/stat_unix.go +++ /dev/null @@ -1,66 +0,0 @@ -//go:build !windows - -package system // import "github.com/docker/docker/pkg/system" - -import ( - "os" - "syscall" -) - -// StatT type contains status of a file. It contains metadata -// like permission, owner, group, size, etc about a file. -type StatT struct { - mode uint32 - uid uint32 - gid uint32 - rdev uint64 - size int64 - mtim syscall.Timespec -} - -// Mode returns file's permission mode. -func (s StatT) Mode() uint32 { - return s.mode -} - -// UID returns file's user id of owner. -func (s StatT) UID() uint32 { - return s.uid -} - -// GID returns file's group id of owner. -func (s StatT) GID() uint32 { - return s.gid -} - -// Rdev returns file's device ID (if it's special file). -func (s StatT) Rdev() uint64 { - return s.rdev -} - -// Size returns file's size. -func (s StatT) Size() int64 { - return s.size -} - -// Mtim returns file's last modification time. -func (s StatT) Mtim() syscall.Timespec { - return s.mtim -} - -// IsDir reports whether s describes a directory. -func (s StatT) IsDir() bool { - return s.mode&syscall.S_IFDIR != 0 -} - -// Stat takes a path to a file and returns -// a system.StatT type pertaining to that file. -// -// Throws an error if the file does not exist -func Stat(path string) (*StatT, error) { - s := &syscall.Stat_t{} - if err := syscall.Stat(path, s); err != nil { - return nil, &os.PathError{Op: "Stat", Path: path, Err: err} - } - return fromStatT(s) -} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_windows.go b/vendor/github.com/docker/docker/pkg/system/stat_windows.go deleted file mode 100644 index 10876cd73..000000000 --- a/vendor/github.com/docker/docker/pkg/system/stat_windows.go +++ /dev/null @@ -1,50 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import ( - "os" - "time" -) - -// StatT type contains status of a file. It contains metadata -// like permission, size, etc about a file. -type StatT struct { - mode os.FileMode - size int64 - mtim time.Time -} - -// Size returns file's size. -func (s StatT) Size() int64 { - return s.size -} - -// Mode returns file's permission mode. -func (s StatT) Mode() os.FileMode { - return s.mode -} - -// Mtim returns file's last modification time. -func (s StatT) Mtim() time.Time { - return s.mtim -} - -// Stat takes a path to a file and returns -// a system.StatT type pertaining to that file. -// -// Throws an error if the file does not exist -func Stat(path string) (*StatT, error) { - fi, err := os.Stat(path) - if err != nil { - return nil, err - } - return fromStatT(&fi) -} - -// fromStatT converts a os.FileInfo type to a system.StatT type -func fromStatT(fi *os.FileInfo) (*StatT, error) { - return &StatT{ - size: (*fi).Size(), - mode: (*fi).Mode(), - mtim: (*fi).ModTime(), - }, nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_unix.go b/vendor/github.com/docker/docker/pkg/system/utimes_unix.go deleted file mode 100644 index f3a079f88..000000000 --- a/vendor/github.com/docker/docker/pkg/system/utimes_unix.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build linux || freebsd - -package system // import "github.com/docker/docker/pkg/system" - -import ( - "syscall" - - "golang.org/x/sys/unix" -) - -// LUtimesNano is used to change access and modification time of the specified path. -// It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm. -func LUtimesNano(path string, ts []syscall.Timespec) error { - uts := []unix.Timespec{ - unix.NsecToTimespec(syscall.TimespecToNsec(ts[0])), - unix.NsecToTimespec(syscall.TimespecToNsec(ts[1])), - } - err := unix.UtimesNanoAt(unix.AT_FDCWD, path, uts, unix.AT_SYMLINK_NOFOLLOW) - if err != nil && err != unix.ENOSYS { - return err - } - - return nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go b/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go deleted file mode 100644 index 7c19d5915..000000000 --- a/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !linux && !freebsd - -package system // import "github.com/docker/docker/pkg/system" - -import "syscall" - -// LUtimesNano is only supported on linux and freebsd. -func LUtimesNano(path string, ts []syscall.Timespec) error { - return ErrNotSupportedPlatform -} diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs.go b/vendor/github.com/docker/docker/pkg/system/xattrs.go deleted file mode 100644 index b3f4e8a21..000000000 --- a/vendor/github.com/docker/docker/pkg/system/xattrs.go +++ /dev/null @@ -1,18 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -type XattrError struct { - Op string - Attr string - Path string - Err error -} - -func (e *XattrError) Error() string { return e.Op + " " + e.Attr + " " + e.Path + ": " + e.Err.Error() } - -func (e *XattrError) Unwrap() error { return e.Err } - -// Timeout reports whether this error represents a timeout. -func (e *XattrError) Timeout() bool { - t, ok := e.Err.(interface{ Timeout() bool }) - return ok && t.Timeout() -} diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go deleted file mode 100644 index facfbb312..000000000 --- a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go +++ /dev/null @@ -1,47 +0,0 @@ -package system // import "github.com/docker/docker/pkg/system" - -import ( - "golang.org/x/sys/unix" -) - -// Lgetxattr retrieves the value of the extended attribute identified by attr -// and associated with the given path in the file system. -// It will returns a nil slice and nil error if the xattr is not set. -func Lgetxattr(path string, attr string) ([]byte, error) { - sysErr := func(err error) ([]byte, error) { - return nil, &XattrError{Op: "lgetxattr", Attr: attr, Path: path, Err: err} - } - - // Start with a 128 length byte array - dest := make([]byte, 128) - sz, errno := unix.Lgetxattr(path, attr, dest) - - for errno == unix.ERANGE { - // Buffer too small, use zero-sized buffer to get the actual size - sz, errno = unix.Lgetxattr(path, attr, []byte{}) - if errno != nil { - return sysErr(errno) - } - dest = make([]byte, sz) - sz, errno = unix.Lgetxattr(path, attr, dest) - } - - switch { - case errno == unix.ENODATA: - return nil, nil - case errno != nil: - return sysErr(errno) - } - - return dest[:sz], nil -} - -// Lsetxattr sets the value of the extended attribute identified by attr -// and associated with the given path in the file system. -func Lsetxattr(path string, attr string, data []byte, flags int) error { - err := unix.Lsetxattr(path, attr, data, flags) - if err != nil { - return &XattrError{Op: "lsetxattr", Attr: attr, Path: path, Err: err} - } - return nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go b/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go deleted file mode 100644 index 2a3698f12..000000000 --- a/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !linux - -package system // import "github.com/docker/docker/pkg/system" - -// Lgetxattr is not supported on platforms other than linux. -func Lgetxattr(path string, attr string) ([]byte, error) { - return nil, ErrNotSupportedPlatform -} - -// Lsetxattr is not supported on platforms other than linux. -func Lsetxattr(path string, attr string, data []byte, flags int) error { - return ErrNotSupportedPlatform -} diff --git a/vendor/github.com/docker/docker/registry/auth.go b/vendor/github.com/docker/docker/registry/auth.go index 905ccf5f5..8c62b83c0 100644 --- a/vendor/github.com/docker/docker/registry/auth.go +++ b/vendor/github.com/docker/docker/registry/auth.go @@ -66,23 +66,23 @@ func (scs staticCredentialStore) SetRefreshToken(*url.URL, string, string) { // loginV2 tries to login to the v2 registry server. The given registry // endpoint will be pinged to get authorization challenges. These challenges // will be used to authenticate against the registry to validate credentials. -func loginV2(authConfig *registry.AuthConfig, endpoint APIEndpoint, userAgent string) (string, string, error) { - var ( - endpointStr = strings.TrimRight(endpoint.URL.String(), "/") + "/v2/" - modifiers = Headers(userAgent, nil) - authTransport = transport.NewTransport(newTransport(endpoint.TLSConfig), modifiers...) - credentialAuthConfig = *authConfig - creds = loginCredentialStore{authConfig: &credentialAuthConfig} - ) - +func loginV2(authConfig *registry.AuthConfig, endpoint APIEndpoint, userAgent string) (status string, token string, _ error) { + endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/" log.G(context.TODO()).Debugf("attempting v2 login to registry endpoint %s", endpointStr) - loginClient, err := v2AuthHTTPClient(endpoint.URL, authTransport, modifiers, creds, nil) + req, err := http.NewRequest(http.MethodGet, endpointStr, nil) if err != nil { return "", "", err } - req, err := http.NewRequest(http.MethodGet, endpointStr, nil) + var ( + modifiers = Headers(userAgent, nil) + authTrans = transport.NewTransport(newTransport(endpoint.TLSConfig), modifiers...) + credentialAuthConfig = *authConfig + creds = loginCredentialStore{authConfig: &credentialAuthConfig} + ) + + loginClient, err := v2AuthHTTPClient(endpoint.URL, authTrans, modifiers, creds, nil) if err != nil { return "", "", err } @@ -133,12 +133,13 @@ func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifi // files). func ConvertToHostname(url string) string { stripped := url - if strings.HasPrefix(url, "http://") { - stripped = strings.TrimPrefix(url, "http://") - } else if strings.HasPrefix(url, "https://") { - stripped = strings.TrimPrefix(url, "https://") + if strings.HasPrefix(stripped, "http://") { + stripped = strings.TrimPrefix(stripped, "http://") + } else if strings.HasPrefix(stripped, "https://") { + stripped = strings.TrimPrefix(stripped, "https://") } - return strings.SplitN(stripped, "/", 2)[0] + stripped, _, _ = strings.Cut(stripped, "/") + return stripped } // ResolveAuthConfig matches an auth configuration to a server address or a URL diff --git a/vendor/github.com/docker/docker/registry/config.go b/vendor/github.com/docker/docker/registry/config.go index 84b0a63ad..f8d94ce80 100644 --- a/vendor/github.com/docker/docker/registry/config.go +++ b/vendor/github.com/docker/docker/registry/config.go @@ -4,20 +4,21 @@ import ( "context" "net" "net/url" - "regexp" "strconv" "strings" "github.com/containerd/log" "github.com/distribution/reference" "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/internal/lazyregexp" ) // ServiceOptions holds command line options. type ServiceOptions struct { - AllowNondistributableArtifacts []string `json:"allow-nondistributable-artifacts,omitempty"` - Mirrors []string `json:"registry-mirrors,omitempty"` - InsecureRegistries []string `json:"insecure-registries,omitempty"` + AllowNondistributableArtifacts []string `json:"allow-nondistributable-artifacts,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. + + Mirrors []string `json:"registry-mirrors,omitempty"` + InsecureRegistries []string `json:"insecure-registries,omitempty"` } // serviceConfig holds daemon configuration for the registry service. @@ -56,10 +57,7 @@ var ( } emptyServiceConfig, _ = newServiceConfig(ServiceOptions{}) - validHostPortRegex = regexp.MustCompile(`^` + reference.DomainRegexp.String() + `$`) - - // for mocking in unit tests - lookupIP = net.LookupIP + validHostPortRegex = lazyregexp.New(`^` + reference.DomainRegexp.String() + `$`) // certsDir is used to override defaultCertsDir. certsDir string @@ -83,9 +81,6 @@ func CertsDir() string { // newServiceConfig returns a new instance of ServiceConfig func newServiceConfig(options ServiceOptions) (*serviceConfig, error) { config := &serviceConfig{} - if err := config.loadAllowNondistributableArtifacts(options.AllowNondistributableArtifacts); err != nil { - return nil, err - } if err := config.loadMirrors(options.Mirrors); err != nil { return nil, err } @@ -103,51 +98,12 @@ func (config *serviceConfig) copy() *registry.ServiceConfig { ic[key] = value } return ®istry.ServiceConfig{ - AllowNondistributableArtifactsCIDRs: append([]*registry.NetIPNet(nil), config.AllowNondistributableArtifactsCIDRs...), - AllowNondistributableArtifactsHostnames: append([]string(nil), config.AllowNondistributableArtifactsHostnames...), - InsecureRegistryCIDRs: append([]*registry.NetIPNet(nil), config.InsecureRegistryCIDRs...), - IndexConfigs: ic, - Mirrors: append([]string(nil), config.Mirrors...), + InsecureRegistryCIDRs: append([]*registry.NetIPNet(nil), config.InsecureRegistryCIDRs...), + IndexConfigs: ic, + Mirrors: append([]string(nil), config.Mirrors...), } } -// loadAllowNondistributableArtifacts loads allow-nondistributable-artifacts registries into config. -func (config *serviceConfig) loadAllowNondistributableArtifacts(registries []string) error { - cidrs := map[string]*registry.NetIPNet{} - hostnames := map[string]bool{} - - for _, r := range registries { - if _, err := ValidateIndexName(r); err != nil { - return err - } - if hasScheme(r) { - return invalidParamf("allow-nondistributable-artifacts registry %s should not contain '://'", r) - } - - if _, ipnet, err := net.ParseCIDR(r); err == nil { - // Valid CIDR. - cidrs[ipnet.String()] = (*registry.NetIPNet)(ipnet) - } else if err = validateHostPort(r); err == nil { - // Must be `host:port` if not CIDR. - hostnames[r] = true - } else { - return invalidParamWrapf(err, "allow-nondistributable-artifacts registry %s is not valid", r) - } - } - - config.AllowNondistributableArtifactsCIDRs = make([]*registry.NetIPNet, 0, len(cidrs)) - for _, c := range cidrs { - config.AllowNondistributableArtifactsCIDRs = append(config.AllowNondistributableArtifactsCIDRs, c) - } - - config.AllowNondistributableArtifactsHostnames = make([]string, 0, len(hostnames)) - for h := range hostnames { - config.AllowNondistributableArtifactsHostnames = append(config.AllowNondistributableArtifactsHostnames, h) - } - - return nil -} - // loadMirrors loads mirrors to config, after removing duplicates. // Returns an error if mirrors contains an invalid mirror. func (config *serviceConfig) loadMirrors(mirrors []string) error { @@ -184,7 +140,7 @@ func (config *serviceConfig) loadMirrors(mirrors []string) error { func (config *serviceConfig) loadInsecureRegistries(registries []string) error { // Localhost is by default considered as an insecure registry. This is a // stop-gap for people who are running a private registry on localhost. - registries = append(registries, "127.0.0.0/8") + registries = append(registries, "::1/128", "127.0.0.0/8") var ( insecureRegistryCIDRs = make([]*registry.NetIPNet, 0) @@ -245,25 +201,6 @@ skip: return nil } -// allowNondistributableArtifacts returns true if the provided hostname is part of the list of registries -// that allow push of nondistributable artifacts. -// -// The list can contain elements with CIDR notation to specify a whole subnet. If the subnet contains an IP -// of the registry specified by hostname, true is returned. -// -// hostname should be a URL.Host (`host:port` or `host`) where the `host` part can be either a domain name -// or an IP address. If it is a domain name, then it will be resolved to IP addresses for matching. If -// resolution fails, CIDR matching is not performed. -func (config *serviceConfig) allowNondistributableArtifacts(hostname string) bool { - for _, h := range config.AllowNondistributableArtifactsHostnames { - if h == hostname { - return true - } - } - - return isCIDRMatch(config.AllowNondistributableArtifactsCIDRs, hostname) -} - // isSecureIndex returns false if the provided indexName is part of the list of insecure registries // Insecure registries accept HTTP and/or accept HTTPS with certificates from unknown CAs. // @@ -285,30 +222,37 @@ func (config *serviceConfig) isSecureIndex(indexName string) bool { return !isCIDRMatch(config.InsecureRegistryCIDRs, indexName) } +// for mocking in unit tests. +var lookupIP = net.LookupIP + // isCIDRMatch returns true if URLHost matches an element of cidrs. URLHost is a URL.Host (`host:port` or `host`) // where the `host` part can be either a domain name or an IP address. If it is a domain name, then it will be // resolved to IP addresses for matching. If resolution fails, false is returned. func isCIDRMatch(cidrs []*registry.NetIPNet, URLHost string) bool { + if len(cidrs) == 0 { + return false + } + host, _, err := net.SplitHostPort(URLHost) if err != nil { - // Assume URLHost is of the form `host` without the port and go on. + // Assume URLHost is a host without port and go on. host = URLHost } - addrs, err := lookupIP(host) - if err != nil { - ip := net.ParseIP(host) - if ip != nil { - addrs = []net.IP{ip} + var addresses []net.IP + if ip := net.ParseIP(host); ip != nil { + // Host is an IP-address. + addresses = append(addresses, ip) + } else { + // Try to resolve the host's IP-address. + addresses, err = lookupIP(host) + if err != nil { + // We failed to resolve the host; assume there's no match. + return false } - - // if ip == nil, then `host` is neither an IP nor it could be looked up, - // either because the index is unreachable, or because the index is behind an HTTP proxy. - // So, len(addrs) == 0 and we're not aborting. } - // Try CIDR notation only if addrs has any elements, i.e. if `host`'s IP could be determined. - for _, addr := range addrs { + for _, addr := range addresses { for _, ipnet := range cidrs { // check if the addr falls in the subnet if (*net.IPNet)(ipnet).Contains(addr) { @@ -359,7 +303,7 @@ func hasScheme(reposName string) bool { } func validateHostPort(s string) error { - // Split host and port, and in case s can not be splitted, assume host only + // Split host and port, and in case s can not be split, assume host only host, port, err := net.SplitHostPort(s) if err != nil { host = s diff --git a/vendor/github.com/docker/docker/registry/registry.go b/vendor/github.com/docker/docker/registry/registry.go index 7866dcd0d..6b079199d 100644 --- a/vendor/github.com/docker/docker/registry/registry.go +++ b/vendor/github.com/docker/docker/registry/registry.go @@ -14,6 +14,7 @@ import ( "github.com/containerd/log" "github.com/docker/distribution/registry/client/transport" "github.com/docker/go-connections/tlsconfig" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) // HostCertsDir returns the config directory for a specific host. @@ -115,7 +116,7 @@ func Headers(userAgent string, metaHeaders http.Header) []transport.RequestModif // newTransport returns a new HTTP transport. If tlsConfig is nil, it uses the // default TLS configuration. -func newTransport(tlsConfig *tls.Config) *http.Transport { +func newTransport(tlsConfig *tls.Config) http.RoundTripper { if tlsConfig == nil { tlsConfig = tlsconfig.ServerDefault() } @@ -125,12 +126,14 @@ func newTransport(tlsConfig *tls.Config) *http.Transport { KeepAlive: 30 * time.Second, } - return &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: direct.DialContext, - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: tlsConfig, - // TODO(dmcgowan): Call close idle connections when complete and use keep alive - DisableKeepAlives: true, - } + return otelhttp.NewTransport( + &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: direct.DialContext, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: tlsConfig, + // TODO(dmcgowan): Call close idle connections when complete and use keep alive + DisableKeepAlives: true, + }, + ) } diff --git a/vendor/github.com/docker/docker/registry/search_session.go b/vendor/github.com/docker/docker/registry/search_session.go index c334143c6..a0d25c805 100644 --- a/vendor/github.com/docker/docker/registry/search_session.go +++ b/vendor/github.com/docker/docker/registry/search_session.go @@ -6,6 +6,7 @@ import ( _ "crypto/sha512" "encoding/json" "fmt" + "io" "net/http" "net/http/cookiejar" "net/url" @@ -15,7 +16,6 @@ import ( "github.com/containerd/log" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/errdefs" - "github.com/docker/docker/pkg/ioutils" "github.com/pkg/errors" ) @@ -76,6 +76,35 @@ func cloneRequest(r *http.Request) *http.Request { return r2 } +// onEOFReader wraps an io.ReadCloser and a function +// the function will run at the end of file or close the file. +type onEOFReader struct { + Rc io.ReadCloser + Fn func() +} + +func (r *onEOFReader) Read(p []byte) (n int, err error) { + n, err = r.Rc.Read(p) + if err == io.EOF { + r.runFunc() + } + return +} + +// Close closes the file and run the function. +func (r *onEOFReader) Close() error { + err := r.Rc.Close() + r.runFunc() + return err +} + +func (r *onEOFReader) runFunc() { + if fn := r.Fn; fn != nil { + fn() + r.Fn = nil + } +} + // RoundTrip changes an HTTP request's headers to add the necessary // authentication-related headers func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) { @@ -119,7 +148,7 @@ func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) { if len(resp.Header["X-Docker-Token"]) > 0 { tr.token = resp.Header["X-Docker-Token"] } - resp.Body = &ioutils.OnEOFReader{ + resp.Body = &onEOFReader{ Rc: resp.Body, Fn: func() { tr.mu.Lock() diff --git a/vendor/github.com/docker/docker/registry/service.go b/vendor/github.com/docker/docker/registry/service.go index 6881c1105..4d66523c6 100644 --- a/vendor/github.com/docker/docker/registry/service.go +++ b/vendor/github.com/docker/docker/registry/service.go @@ -68,10 +68,11 @@ func (s *Service) Auth(ctx context.Context, authConfig *registry.AuthConfig, use registryHostName = u.Host } - // Lookup endpoints for authentication using "LookupPushEndpoints", which - // excludes mirrors to prevent sending credentials of the upstream registry - // to a mirror. - endpoints, err := s.LookupPushEndpoints(registryHostName) + // Lookup endpoints for authentication but exclude mirrors to prevent + // sending credentials of the upstream registry to a mirror. + s.mu.RLock() + endpoints, err := s.lookupV2Endpoints(registryHostName, false) + s.mu.RUnlock() if err != nil { return "", "", invalidParam(err) } @@ -103,10 +104,9 @@ func (s *Service) ResolveRepository(name reference.Named) (*RepositoryInfo, erro type APIEndpoint struct { Mirror bool URL *url.URL - Version APIVersion // Deprecated: v1 registries are deprecated, and endpoints are always v2. - AllowNondistributableArtifacts bool + AllowNondistributableArtifacts bool // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. Official bool - TrimHostname bool + TrimHostname bool // Deprecated: hostname is now trimmed unconditionally for remote names. This field will be removed in the next release. TLSConfig *tls.Config } @@ -116,7 +116,7 @@ func (s *Service) LookupPullEndpoints(hostname string) (endpoints []APIEndpoint, s.mu.RLock() defer s.mu.RUnlock() - return s.lookupV2Endpoints(hostname) + return s.lookupV2Endpoints(hostname, true) } // LookupPushEndpoints creates a list of v2 endpoints to try to push to, in order of preference. @@ -125,15 +125,7 @@ func (s *Service) LookupPushEndpoints(hostname string) (endpoints []APIEndpoint, s.mu.RLock() defer s.mu.RUnlock() - allEndpoints, err := s.lookupV2Endpoints(hostname) - if err == nil { - for _, endpoint := range allEndpoints { - if !endpoint.Mirror { - endpoints = append(endpoints, endpoint) - } - } - } - return endpoints, err + return s.lookupV2Endpoints(hostname, false) } // IsInsecureRegistry returns true if the registry at given host is configured as diff --git a/vendor/github.com/docker/docker/registry/service_v2.go b/vendor/github.com/docker/docker/registry/service_v2.go index 5d09e11c9..43754527a 100644 --- a/vendor/github.com/docker/docker/registry/service_v2.go +++ b/vendor/github.com/docker/docker/registry/service_v2.go @@ -7,38 +7,33 @@ import ( "github.com/docker/go-connections/tlsconfig" ) -func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, err error) { - ana := s.config.allowNondistributableArtifacts(hostname) - +func (s *Service) lookupV2Endpoints(hostname string, includeMirrors bool) ([]APIEndpoint, error) { + var endpoints []APIEndpoint if hostname == DefaultNamespace || hostname == IndexHostname { - for _, mirror := range s.config.Mirrors { - if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { - mirror = "https://" + mirror - } - mirrorURL, err := url.Parse(mirror) - if err != nil { - return nil, invalidParam(err) - } - mirrorTLSConfig, err := newTLSConfig(mirrorURL.Host, s.config.isSecureIndex(mirrorURL.Host)) - if err != nil { - return nil, err + if includeMirrors { + for _, mirror := range s.config.Mirrors { + if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { + mirror = "https://" + mirror + } + mirrorURL, err := url.Parse(mirror) + if err != nil { + return nil, invalidParam(err) + } + mirrorTLSConfig, err := newTLSConfig(mirrorURL.Host, s.config.isSecureIndex(mirrorURL.Host)) + if err != nil { + return nil, err + } + endpoints = append(endpoints, APIEndpoint{ + URL: mirrorURL, + Mirror: true, + TLSConfig: mirrorTLSConfig, + }) } - endpoints = append(endpoints, APIEndpoint{ - URL: mirrorURL, - Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. - Mirror: true, - TrimHostname: true, - TLSConfig: mirrorTLSConfig, - }) } endpoints = append(endpoints, APIEndpoint{ - URL: DefaultV2Registry, - Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. - Official: true, - TrimHostname: true, - TLSConfig: tlsconfig.ServerDefault(), - - AllowNondistributableArtifacts: ana, + URL: DefaultV2Registry, + Official: true, + TLSConfig: tlsconfig.ServerDefault(), }) return endpoints, nil @@ -55,10 +50,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e Scheme: "https", Host: hostname, }, - Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. - AllowNondistributableArtifacts: ana, - TrimHostname: true, - TLSConfig: tlsConfig, + TLSConfig: tlsConfig, }, } @@ -68,9 +60,6 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e Scheme: "http", Host: hostname, }, - Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. - AllowNondistributableArtifacts: ana, - TrimHostname: true, // used to check if supposed to be secure via InsecureSkipVerify TLSConfig: tlsConfig, }) diff --git a/vendor/github.com/docker/docker/registry/types.go b/vendor/github.com/docker/docker/registry/types.go index 54aa0bd19..02d7f4f38 100644 --- a/vendor/github.com/docker/docker/registry/types.go +++ b/vendor/github.com/docker/docker/registry/types.go @@ -5,27 +5,6 @@ import ( "github.com/docker/docker/api/types/registry" ) -// APIVersion is an integral representation of an API version (presently -// either 1 or 2) -// -// Deprecated: v1 registries are deprecated, and endpoints are always v2. -type APIVersion int - -func (av APIVersion) String() string { - return apiVersions[av] -} - -// API Version identifiers. -const ( - APIVersion1 APIVersion = 1 // Deprecated: v1 registries are deprecated, and endpoints are always v2. - APIVersion2 APIVersion = 2 // Deprecated: v1 registries are deprecated, and endpoints are always v2. -) - -var apiVersions = map[APIVersion]string{ - APIVersion1: "v1", - APIVersion2: "v2", -} - // RepositoryInfo describes a repository type RepositoryInfo struct { Name reference.Named @@ -37,5 +16,7 @@ type RepositoryInfo struct { Official bool // Class represents the class of the repository, such as "plugin" // or "image". + // + // Deprecated: this field is no longer used, and will be removed in the next release. Class string } diff --git a/vendor/modules.txt b/vendor/modules.txt index b7214af15..3a52fb234 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,3 +1,5 @@ +# github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 +## explicit; go 1.20 # github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 ## explicit; go 1.16 github.com/Azure/go-ansiterm @@ -24,9 +26,6 @@ github.com/cenkalti/backoff/v4 # github.com/cespare/xxhash/v2 v2.3.0 ## explicit; go 1.11 github.com/cespare/xxhash/v2 -# github.com/containerd/containerd v1.7.27 -## explicit; go 1.21 -github.com/containerd/containerd/pkg/userns # github.com/containerd/log v0.1.0 ## explicit; go 1.20 github.com/containerd/log @@ -85,12 +84,13 @@ github.com/docker/distribution/registry/client/transport github.com/docker/distribution/registry/storage/cache github.com/docker/distribution/registry/storage/cache/memory github.com/docker/distribution/uuid -# github.com/docker/docker v27.1.1+incompatible +# github.com/docker/docker v28.0.0+incompatible ## explicit github.com/docker/docker/api github.com/docker/docker/api/types github.com/docker/docker/api/types/blkiodev github.com/docker/docker/api/types/checkpoint +github.com/docker/docker/api/types/common github.com/docker/docker/api/types/container github.com/docker/docker/api/types/events github.com/docker/docker/api/types/filters @@ -98,6 +98,7 @@ github.com/docker/docker/api/types/image github.com/docker/docker/api/types/mount github.com/docker/docker/api/types/network github.com/docker/docker/api/types/registry +github.com/docker/docker/api/types/storage github.com/docker/docker/api/types/strslice github.com/docker/docker/api/types/swarm github.com/docker/docker/api/types/swarm/runtime @@ -107,12 +108,12 @@ github.com/docker/docker/api/types/versions github.com/docker/docker/api/types/volume github.com/docker/docker/client github.com/docker/docker/errdefs +github.com/docker/docker/internal/lazyregexp github.com/docker/docker/internal/multierror github.com/docker/docker/pkg/archive +github.com/docker/docker/pkg/atomicwriter github.com/docker/docker/pkg/idtools github.com/docker/docker/pkg/ioutils -github.com/docker/docker/pkg/pools -github.com/docker/docker/pkg/system github.com/docker/docker/registry # github.com/docker/docker-credential-helpers v0.8.1 ## explicit; go 1.19 @@ -596,6 +597,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry +# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 +## explicit; go 1.20 # go.opentelemetry.io/otel/metric v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/metric