From 83265c9171f8739d78dcbebfc0d94a09451dbf72 Mon Sep 17 00:00:00 2001 From: Davanum Srinivas Date: Tue, 7 Dec 2021 14:48:21 -0500 Subject: [PATCH 1/3] drop files deleted from pkg/kubelet/dockershim Signed-off-by: Davanum Srinivas --- .../containernetworking/cni/LICENSE | 206 ---- .../vendor/github.com/docker/docker/LICENSE | 195 ---- .../github.com/docker/go-connections/LICENSE | 195 ---- .../vendor/github.com/morikuni/aec/LICENSE | 25 - .../opencontainers/image-spec/LICENSE | 195 ---- pkg/kubelet/cadvisor/cadvisor_linux_docker.go | 26 - .../dockershim/cm/container_manager.go | 26 - .../dockershim/cm/container_manager_linux.go | 158 --- .../cm/container_manager_unsupported.go | 38 - .../cm/container_manager_windows.go | 37 - pkg/kubelet/dockershim/convert.go | 181 ---- pkg/kubelet/dockershim/convert_test.go | 74 -- pkg/kubelet/dockershim/doc.go | 22 - pkg/kubelet/dockershim/docker_checkpoint.go | 109 -- .../dockershim/docker_checkpoint_test.go | 36 - pkg/kubelet/dockershim/docker_container.go | 508 ---------- .../dockershim/docker_container_test.go | 370 ------- .../docker_container_unsupported.go | 48 - .../dockershim/docker_container_windows.go | 218 ---- .../docker_container_windows_test.go | 311 ------ pkg/kubelet/dockershim/docker_image.go | 192 ---- pkg/kubelet/dockershim/docker_image_linux.go | 70 -- pkg/kubelet/dockershim/docker_image_test.go | 113 --- .../dockershim/docker_image_unsupported.go | 32 - .../dockershim/docker_image_windows.go | 52 - .../dockershim/docker_legacy_service.go | 132 --- pkg/kubelet/dockershim/docker_logs.go | 32 - pkg/kubelet/dockershim/docker_sandbox.go | 773 --------------- .../dockershim/docker_sandbox_linux_test.go | 39 - pkg/kubelet/dockershim/docker_sandbox_test.go | 314 ------ pkg/kubelet/dockershim/docker_service.go | 579 ----------- pkg/kubelet/dockershim/docker_service_test.go | 171 ---- pkg/kubelet/dockershim/docker_stats.go | 91 -- pkg/kubelet/dockershim/docker_stats_linux.go | 63 -- pkg/kubelet/dockershim/docker_stats_test.go | 82 -- .../dockershim/docker_stats_unsupported.go | 30 - .../dockershim/docker_stats_windows.go | 91 -- pkg/kubelet/dockershim/docker_streaming.go | 209 ---- .../dockershim/docker_streaming_others.go | 87 -- .../dockershim/docker_streaming_windows.go | 39 - pkg/kubelet/dockershim/dockershim_nodocker.go | 20 - pkg/kubelet/dockershim/exec.go | 162 --- pkg/kubelet/dockershim/exec_test.go | 191 ---- pkg/kubelet/dockershim/helpers.go | 442 --------- pkg/kubelet/dockershim/helpers_linux.go | 158 --- pkg/kubelet/dockershim/helpers_linux_test.go | 109 -- pkg/kubelet/dockershim/helpers_test.go | 441 --------- pkg/kubelet/dockershim/helpers_unsupported.go | 62 -- pkg/kubelet/dockershim/helpers_windows.go | 161 --- pkg/kubelet/dockershim/libdocker/client.go | 101 -- .../dockershim/libdocker/fake_client.go | 854 ---------------- pkg/kubelet/dockershim/libdocker/helpers.go | 166 ---- .../dockershim/libdocker/helpers_test.go | 273 ----- .../libdocker/instrumented_client.go | 275 ------ .../libdocker/kube_docker_client.go | 678 ------------- .../libdocker/kube_docker_client_test.go | 36 - .../libdocker/testing/mock_client.go | 407 -------- pkg/kubelet/dockershim/metrics/metrics.go | 105 -- pkg/kubelet/dockershim/naming.go | 152 --- pkg/kubelet/dockershim/naming_test.go | 109 -- pkg/kubelet/dockershim/network/OWNERS | 10 - pkg/kubelet/dockershim/network/cni/cni.go | 472 --------- .../dockershim/network/cni/cni_others.go | 91 -- .../dockershim/network/cni/cni_test.go | 360 ------- .../dockershim/network/cni/cni_windows.go | 92 -- .../network/cni/testing/mock_cni.go | 94 -- .../dockershim/network/hairpin/hairpin.go | 90 -- .../network/hairpin/hairpin_test.go | 112 --- .../network/hostport/fake_iptables.go | 375 ------- .../network/hostport/fake_iptables_test.go | 59 -- .../dockershim/network/hostport/hostport.go | 171 ---- .../network/hostport/hostport_manager.go | 445 --------- .../network/hostport/hostport_manager_test.go | 734 -------------- .../network/hostport/hostport_test.go | 90 -- .../dockershim/network/kubenet/kubenet.go | 24 - .../network/kubenet/kubenet_linux.go | 930 ------------------ .../network/kubenet/kubenet_linux_test.go | 392 -------- .../network/kubenet/kubenet_unsupported.go | 56 -- .../dockershim/network/metrics/metrics.go | 93 -- pkg/kubelet/dockershim/network/network.go | 30 - pkg/kubelet/dockershim/network/plugins.go | 427 -------- .../dockershim/network/plugins_test.go | 69 -- .../dockershim/network/testing/fake_host.go | 69 -- .../network/testing/mock_network_plugin.go | 297 ------ .../network/testing/plugins_test.go | 252 ----- .../dockershim/remote/docker_server.go | 82 -- .../dockershim/remote/docker_server_test.go | 174 ---- pkg/kubelet/dockershim/security_context.go | 207 ---- .../dockershim/security_context_test.go | 494 ---------- pkg/kubelet/dockershim/selinux_util.go | 89 -- pkg/kubelet/dockershim/selinux_util_test.go | 57 -- pkg/kubelet/kubelet_dockershim.go | 80 -- 92 files changed, 18088 deletions(-) delete mode 100644 LICENSES/vendor/github.com/containernetworking/cni/LICENSE delete mode 100644 LICENSES/vendor/github.com/docker/docker/LICENSE delete mode 100644 LICENSES/vendor/github.com/docker/go-connections/LICENSE delete mode 100644 LICENSES/vendor/github.com/morikuni/aec/LICENSE delete mode 100644 LICENSES/vendor/github.com/opencontainers/image-spec/LICENSE delete mode 100644 pkg/kubelet/cadvisor/cadvisor_linux_docker.go delete mode 100644 pkg/kubelet/dockershim/cm/container_manager.go delete mode 100644 pkg/kubelet/dockershim/cm/container_manager_linux.go delete mode 100644 pkg/kubelet/dockershim/cm/container_manager_unsupported.go delete mode 100644 pkg/kubelet/dockershim/cm/container_manager_windows.go delete mode 100644 pkg/kubelet/dockershim/convert.go delete mode 100644 pkg/kubelet/dockershim/convert_test.go delete mode 100644 pkg/kubelet/dockershim/doc.go delete mode 100644 pkg/kubelet/dockershim/docker_checkpoint.go delete mode 100644 pkg/kubelet/dockershim/docker_checkpoint_test.go delete mode 100644 pkg/kubelet/dockershim/docker_container.go delete mode 100644 pkg/kubelet/dockershim/docker_container_test.go delete mode 100644 pkg/kubelet/dockershim/docker_container_unsupported.go delete mode 100644 pkg/kubelet/dockershim/docker_container_windows.go delete mode 100644 pkg/kubelet/dockershim/docker_container_windows_test.go delete mode 100644 pkg/kubelet/dockershim/docker_image.go delete mode 100644 pkg/kubelet/dockershim/docker_image_linux.go delete mode 100644 pkg/kubelet/dockershim/docker_image_test.go delete mode 100644 pkg/kubelet/dockershim/docker_image_unsupported.go delete mode 100644 pkg/kubelet/dockershim/docker_image_windows.go delete mode 100644 pkg/kubelet/dockershim/docker_legacy_service.go delete mode 100644 pkg/kubelet/dockershim/docker_logs.go delete mode 100644 pkg/kubelet/dockershim/docker_sandbox.go delete mode 100644 pkg/kubelet/dockershim/docker_sandbox_linux_test.go delete mode 100644 pkg/kubelet/dockershim/docker_sandbox_test.go delete mode 100644 pkg/kubelet/dockershim/docker_service.go delete mode 100644 pkg/kubelet/dockershim/docker_service_test.go delete mode 100644 pkg/kubelet/dockershim/docker_stats.go delete mode 100644 pkg/kubelet/dockershim/docker_stats_linux.go delete mode 100644 pkg/kubelet/dockershim/docker_stats_test.go delete mode 100644 pkg/kubelet/dockershim/docker_stats_unsupported.go delete mode 100644 pkg/kubelet/dockershim/docker_stats_windows.go delete mode 100644 pkg/kubelet/dockershim/docker_streaming.go delete mode 100644 pkg/kubelet/dockershim/docker_streaming_others.go delete mode 100644 pkg/kubelet/dockershim/docker_streaming_windows.go delete mode 100644 pkg/kubelet/dockershim/dockershim_nodocker.go delete mode 100644 pkg/kubelet/dockershim/exec.go delete mode 100644 pkg/kubelet/dockershim/exec_test.go delete mode 100644 pkg/kubelet/dockershim/helpers.go delete mode 100644 pkg/kubelet/dockershim/helpers_linux.go delete mode 100644 pkg/kubelet/dockershim/helpers_linux_test.go delete mode 100644 pkg/kubelet/dockershim/helpers_test.go delete mode 100644 pkg/kubelet/dockershim/helpers_unsupported.go delete mode 100644 pkg/kubelet/dockershim/helpers_windows.go delete mode 100644 pkg/kubelet/dockershim/libdocker/client.go delete mode 100644 pkg/kubelet/dockershim/libdocker/fake_client.go delete mode 100644 pkg/kubelet/dockershim/libdocker/helpers.go delete mode 100644 pkg/kubelet/dockershim/libdocker/helpers_test.go delete mode 100644 pkg/kubelet/dockershim/libdocker/instrumented_client.go delete mode 100644 pkg/kubelet/dockershim/libdocker/kube_docker_client.go delete mode 100644 pkg/kubelet/dockershim/libdocker/kube_docker_client_test.go delete mode 100644 pkg/kubelet/dockershim/libdocker/testing/mock_client.go delete mode 100644 pkg/kubelet/dockershim/metrics/metrics.go delete mode 100644 pkg/kubelet/dockershim/naming.go delete mode 100644 pkg/kubelet/dockershim/naming_test.go delete mode 100644 pkg/kubelet/dockershim/network/OWNERS delete mode 100644 pkg/kubelet/dockershim/network/cni/cni.go delete mode 100644 pkg/kubelet/dockershim/network/cni/cni_others.go delete mode 100644 pkg/kubelet/dockershim/network/cni/cni_test.go delete mode 100644 pkg/kubelet/dockershim/network/cni/cni_windows.go delete mode 100644 pkg/kubelet/dockershim/network/cni/testing/mock_cni.go delete mode 100644 pkg/kubelet/dockershim/network/hairpin/hairpin.go delete mode 100644 pkg/kubelet/dockershim/network/hairpin/hairpin_test.go delete mode 100644 pkg/kubelet/dockershim/network/hostport/fake_iptables.go delete mode 100644 pkg/kubelet/dockershim/network/hostport/fake_iptables_test.go delete mode 100644 pkg/kubelet/dockershim/network/hostport/hostport.go delete mode 100644 pkg/kubelet/dockershim/network/hostport/hostport_manager.go delete mode 100644 pkg/kubelet/dockershim/network/hostport/hostport_manager_test.go delete mode 100644 pkg/kubelet/dockershim/network/hostport/hostport_test.go delete mode 100644 pkg/kubelet/dockershim/network/kubenet/kubenet.go delete mode 100644 pkg/kubelet/dockershim/network/kubenet/kubenet_linux.go delete mode 100644 pkg/kubelet/dockershim/network/kubenet/kubenet_linux_test.go delete mode 100644 pkg/kubelet/dockershim/network/kubenet/kubenet_unsupported.go delete mode 100644 pkg/kubelet/dockershim/network/metrics/metrics.go delete mode 100644 pkg/kubelet/dockershim/network/network.go delete mode 100644 pkg/kubelet/dockershim/network/plugins.go delete mode 100644 pkg/kubelet/dockershim/network/plugins_test.go delete mode 100644 pkg/kubelet/dockershim/network/testing/fake_host.go delete mode 100644 pkg/kubelet/dockershim/network/testing/mock_network_plugin.go delete mode 100644 pkg/kubelet/dockershim/network/testing/plugins_test.go delete mode 100644 pkg/kubelet/dockershim/remote/docker_server.go delete mode 100644 pkg/kubelet/dockershim/remote/docker_server_test.go delete mode 100644 pkg/kubelet/dockershim/security_context.go delete mode 100644 pkg/kubelet/dockershim/security_context_test.go delete mode 100644 pkg/kubelet/dockershim/selinux_util.go delete mode 100644 pkg/kubelet/dockershim/selinux_util_test.go delete mode 100644 pkg/kubelet/kubelet_dockershim.go diff --git a/LICENSES/vendor/github.com/containernetworking/cni/LICENSE b/LICENSES/vendor/github.com/containernetworking/cni/LICENSE deleted file mode 100644 index 3b1d199f53b..00000000000 --- a/LICENSES/vendor/github.com/containernetworking/cni/LICENSE +++ /dev/null @@ -1,206 +0,0 @@ -= vendor/github.com/containernetworking/cni licensed under: = - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - -= vendor/github.com/containernetworking/cni/LICENSE fa818a259cbed7ce8bc2a22d35a464fc diff --git a/LICENSES/vendor/github.com/docker/docker/LICENSE b/LICENSES/vendor/github.com/docker/docker/LICENSE deleted file mode 100644 index 48c33574e4c..00000000000 --- a/LICENSES/vendor/github.com/docker/docker/LICENSE +++ /dev/null @@ -1,195 +0,0 @@ -= vendor/github.com/docker/docker licensed under: = - - - 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 2013-2018 Docker, Inc. - - 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. - -= vendor/github.com/docker/docker/LICENSE 4859e97a9c7780e77972d989f0823f28 diff --git a/LICENSES/vendor/github.com/docker/go-connections/LICENSE b/LICENSES/vendor/github.com/docker/go-connections/LICENSE deleted file mode 100644 index 08061a0926b..00000000000 --- a/LICENSES/vendor/github.com/docker/go-connections/LICENSE +++ /dev/null @@ -1,195 +0,0 @@ -= vendor/github.com/docker/go-connections licensed under: = - - - 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 2015 Docker, Inc. - - 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. - -= vendor/github.com/docker/go-connections/LICENSE 04424bc6f5a5be60691b9824d65c2ad8 diff --git a/LICENSES/vendor/github.com/morikuni/aec/LICENSE b/LICENSES/vendor/github.com/morikuni/aec/LICENSE deleted file mode 100644 index d710121aa78..00000000000 --- a/LICENSES/vendor/github.com/morikuni/aec/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -= vendor/github.com/morikuni/aec licensed under: = - -The MIT License (MIT) - -Copyright (c) 2016 Taihei Morikuni - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -= vendor/github.com/morikuni/aec/LICENSE 86852eb2df591157c788f3ba889c8aec diff --git a/LICENSES/vendor/github.com/opencontainers/image-spec/LICENSE b/LICENSES/vendor/github.com/opencontainers/image-spec/LICENSE deleted file mode 100644 index b4ccc319f02..00000000000 --- a/LICENSES/vendor/github.com/opencontainers/image-spec/LICENSE +++ /dev/null @@ -1,195 +0,0 @@ -= vendor/github.com/opencontainers/image-spec licensed under: = - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2016 The Linux Foundation. - - 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. - -= vendor/github.com/opencontainers/image-spec/LICENSE 27ef03aa2da6e424307f102e8b42621d diff --git a/pkg/kubelet/cadvisor/cadvisor_linux_docker.go b/pkg/kubelet/cadvisor/cadvisor_linux_docker.go deleted file mode 100644 index cdd975efffd..00000000000 --- a/pkg/kubelet/cadvisor/cadvisor_linux_docker.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cadvisor - -import ( - // We only want to perform this docker specific cadvisor init when we are not - // using the `dockerless` build tag. - _ "github.com/google/cadvisor/container/docker/install" -) diff --git a/pkg/kubelet/dockershim/cm/container_manager.go b/pkg/kubelet/dockershim/cm/container_manager.go deleted file mode 100644 index f2255cd9ec0..00000000000 --- a/pkg/kubelet/dockershim/cm/container_manager.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cm - -// ContainerManager is an interface that abstracts the basic operations of a -// container manager. -type ContainerManager interface { - Start() error -} diff --git a/pkg/kubelet/dockershim/cm/container_manager_linux.go b/pkg/kubelet/dockershim/cm/container_manager_linux.go deleted file mode 100644 index 759e27f26c5..00000000000 --- a/pkg/kubelet/dockershim/cm/container_manager_linux.go +++ /dev/null @@ -1,158 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cm - -import ( - "fmt" - "io/ioutil" - "regexp" - "strconv" - "time" - - "github.com/opencontainers/runc/libcontainer/cgroups" - cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" - "github.com/opencontainers/runc/libcontainer/configs" - utilversion "k8s.io/apimachinery/pkg/util/version" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/klog/v2" - kubecm "k8s.io/kubernetes/pkg/kubelet/cm" - - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -const ( - // The percent of the machine memory capacity. The value is used to calculate - // docker memory resource container's hardlimit to workaround docker memory - // leakage issue. Please see kubernetes/issues/9881 for more detail. - dockerMemoryLimitThresholdPercent = 70 - - // The minimum memory limit allocated to docker container: 150Mi - minDockerMemoryLimit = 150 * 1024 * 1024 - - // The OOM score adjustment for the docker process (i.e. the docker - // daemon). Essentially, makes docker very unlikely to experience an oom - // kill. - dockerOOMScoreAdj = -999 -) - -var ( - memoryCapacityRegexp = regexp.MustCompile(`MemTotal:\s*([0-9]+) kB`) -) - -// NewContainerManager creates a new instance of ContainerManager -func NewContainerManager(cgroupsName string, client libdocker.Interface) ContainerManager { - return &containerManager{ - cgroupsName: cgroupsName, - client: client, - } -} - -type containerManager struct { - // Docker client. - client libdocker.Interface - // Name of the cgroups. - cgroupsName string - // Manager for the cgroups. - cgroupsManager cgroups.Manager -} - -func (m *containerManager) Start() error { - // TODO: check if the required cgroups are mounted. - if len(m.cgroupsName) != 0 { - manager, err := createCgroupManager(m.cgroupsName) - if err != nil { - return err - } - m.cgroupsManager = manager - } - go wait.Until(m.doWork, 5*time.Minute, wait.NeverStop) - return nil -} - -func (m *containerManager) doWork() { - v, err := m.client.Version() - if err != nil { - klog.ErrorS(err, "Unable to get docker version") - return - } - version, err := utilversion.ParseGeneric(v.APIVersion) - if err != nil { - klog.ErrorS(err, "Unable to parse docker version", "dockerVersion", v.APIVersion) - return - } - // EnsureDockerInContainer does two things. - // 1. Ensure processes run in the cgroups if m.cgroupsManager is not nil. - // 2. Ensure processes have the OOM score applied. - if err := kubecm.EnsureDockerInContainer(version, dockerOOMScoreAdj, m.cgroupsManager); err != nil { - klog.ErrorS(err, "Unable to ensure the docker processes run in the desired containers") - } -} - -func createCgroupManager(name string) (cgroups.Manager, error) { - var memoryLimit uint64 - - memoryCapacity, err := getMemoryCapacity() - if err != nil { - klog.ErrorS(err, "Failed to get the memory capacity on machine") - } else { - memoryLimit = memoryCapacity * dockerMemoryLimitThresholdPercent / 100 - } - - if err != nil || memoryLimit < minDockerMemoryLimit { - memoryLimit = minDockerMemoryLimit - } - klog.V(2).InfoS("Configure resource-only container with memory limit", "containerName", name, "memoryLimit", memoryLimit) - - cg := &configs.Cgroup{ - Parent: "/", - Name: name, - Resources: &configs.Resources{ - Memory: int64(memoryLimit), - MemorySwap: -1, - SkipDevices: true, - }, - } - return cgroupfs.NewManager(cg, nil, false), nil -} - -// getMemoryCapacity returns the memory capacity on the machine in bytes. -func getMemoryCapacity() (uint64, error) { - out, err := ioutil.ReadFile("/proc/meminfo") - if err != nil { - return 0, err - } - return parseCapacity(out, memoryCapacityRegexp) -} - -// parseCapacity matches a Regexp in a []byte, returning the resulting value in bytes. -// Assumes that the value matched by the Regexp is in KB. -func parseCapacity(b []byte, r *regexp.Regexp) (uint64, error) { - matches := r.FindSubmatch(b) - if len(matches) != 2 { - return 0, fmt.Errorf("failed to match regexp in output: %q", string(b)) - } - m, err := strconv.ParseUint(string(matches[1]), 10, 64) - if err != nil { - return 0, err - } - - // Convert to bytes. - return m * 1024, err -} diff --git a/pkg/kubelet/dockershim/cm/container_manager_unsupported.go b/pkg/kubelet/dockershim/cm/container_manager_unsupported.go deleted file mode 100644 index 6c9bd354446..00000000000 --- a/pkg/kubelet/dockershim/cm/container_manager_unsupported.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build !linux && !windows && !dockerless -// +build !linux,!windows,!dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cm - -import ( - "fmt" - - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -type unsupportedContainerManager struct { -} - -// NewContainerManager creates a new instance of ContainerManager -func NewContainerManager(_ string, _ libdocker.Interface) ContainerManager { - return &unsupportedContainerManager{} -} - -func (m *unsupportedContainerManager) Start() error { - return fmt.Errorf("Container Manager is unsupported in this build") -} diff --git a/pkg/kubelet/dockershim/cm/container_manager_windows.go b/pkg/kubelet/dockershim/cm/container_manager_windows.go deleted file mode 100644 index 135c20c15d6..00000000000 --- a/pkg/kubelet/dockershim/cm/container_manager_windows.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build windows && !dockerless -// +build windows,!dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cm - -import ( - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -// no-op -type containerManager struct { -} - -// NewContainerManager creates a new instance of ContainerManager -func NewContainerManager(_ string, _ libdocker.Interface) ContainerManager { - return &containerManager{} -} - -func (m *containerManager) Start() error { - return nil -} diff --git a/pkg/kubelet/dockershim/convert.go b/pkg/kubelet/dockershim/convert.go deleted file mode 100644 index dcbe9d07333..00000000000 --- a/pkg/kubelet/dockershim/convert.go +++ /dev/null @@ -1,181 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - "strings" - "time" - - dockertypes "github.com/docker/docker/api/types" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -// This file contains helper functions to convert docker API types to runtime -// API types, or vice versa. - -func imageToRuntimeAPIImage(image *dockertypes.ImageSummary) (*runtimeapi.Image, error) { - if image == nil { - return nil, fmt.Errorf("unable to convert a nil pointer to a runtime API image") - } - - size := uint64(image.VirtualSize) - return &runtimeapi.Image{ - Id: image.ID, - RepoTags: image.RepoTags, - RepoDigests: image.RepoDigests, - Size_: size, - }, nil -} - -func imageInspectToRuntimeAPIImage(image *dockertypes.ImageInspect) (*runtimeapi.Image, error) { - if image == nil || image.Config == nil { - return nil, fmt.Errorf("unable to convert a nil pointer to a runtime API image") - } - - size := uint64(image.VirtualSize) - runtimeImage := &runtimeapi.Image{ - Id: image.ID, - RepoTags: image.RepoTags, - RepoDigests: image.RepoDigests, - Size_: size, - } - - uid, username := getUserFromImageUser(image.Config.User) - if uid != nil { - runtimeImage.Uid = &runtimeapi.Int64Value{Value: *uid} - } - runtimeImage.Username = username - return runtimeImage, nil -} - -func toPullableImageID(id string, image *dockertypes.ImageInspect) string { - // Default to the image ID, but if RepoDigests is not empty, use - // the first digest instead. - imageID := DockerImageIDPrefix + id - if image != nil && len(image.RepoDigests) > 0 { - imageID = DockerPullableImageIDPrefix + image.RepoDigests[0] - } - return imageID -} - -func toRuntimeAPIContainer(c *dockertypes.Container) (*runtimeapi.Container, error) { - state := toRuntimeAPIContainerState(c.Status) - if len(c.Names) == 0 { - return nil, fmt.Errorf("unexpected empty container name: %+v", c) - } - metadata, err := parseContainerName(c.Names[0]) - if err != nil { - return nil, err - } - labels, annotations := extractLabels(c.Labels) - sandboxID := c.Labels[sandboxIDLabelKey] - // The timestamp in dockertypes.Container is in seconds. - createdAt := c.Created * int64(time.Second) - return &runtimeapi.Container{ - Id: c.ID, - PodSandboxId: sandboxID, - Metadata: metadata, - Image: &runtimeapi.ImageSpec{Image: c.Image}, - ImageRef: c.ImageID, - State: state, - CreatedAt: createdAt, - Labels: labels, - Annotations: annotations, - }, nil -} - -func toDockerContainerStatus(state runtimeapi.ContainerState) string { - switch state { - case runtimeapi.ContainerState_CONTAINER_CREATED: - return "created" - case runtimeapi.ContainerState_CONTAINER_RUNNING: - return "running" - case runtimeapi.ContainerState_CONTAINER_EXITED: - return "exited" - case runtimeapi.ContainerState_CONTAINER_UNKNOWN: - fallthrough - default: - return "unknown" - } -} - -func toRuntimeAPIContainerState(state string) runtimeapi.ContainerState { - // Parse the state string in dockertypes.Container. This could break when - // we upgrade docker. - switch { - case strings.HasPrefix(state, libdocker.StatusRunningPrefix): - return runtimeapi.ContainerState_CONTAINER_RUNNING - case strings.HasPrefix(state, libdocker.StatusExitedPrefix): - return runtimeapi.ContainerState_CONTAINER_EXITED - case strings.HasPrefix(state, libdocker.StatusCreatedPrefix): - return runtimeapi.ContainerState_CONTAINER_CREATED - default: - return runtimeapi.ContainerState_CONTAINER_UNKNOWN - } -} - -func toRuntimeAPISandboxState(state string) runtimeapi.PodSandboxState { - // Parse the state string in dockertypes.Container. This could break when - // we upgrade docker. - switch { - case strings.HasPrefix(state, libdocker.StatusRunningPrefix): - return runtimeapi.PodSandboxState_SANDBOX_READY - default: - return runtimeapi.PodSandboxState_SANDBOX_NOTREADY - } -} - -func containerToRuntimeAPISandbox(c *dockertypes.Container) (*runtimeapi.PodSandbox, error) { - state := toRuntimeAPISandboxState(c.Status) - if len(c.Names) == 0 { - return nil, fmt.Errorf("unexpected empty sandbox name: %+v", c) - } - metadata, err := parseSandboxName(c.Names[0]) - if err != nil { - return nil, err - } - labels, annotations := extractLabels(c.Labels) - // The timestamp in dockertypes.Container is in seconds. - createdAt := c.Created * int64(time.Second) - return &runtimeapi.PodSandbox{ - Id: c.ID, - Metadata: metadata, - State: state, - CreatedAt: createdAt, - Labels: labels, - Annotations: annotations, - }, nil -} - -func checkpointToRuntimeAPISandbox(id string, checkpoint ContainerCheckpoint) *runtimeapi.PodSandbox { - state := runtimeapi.PodSandboxState_SANDBOX_NOTREADY - _, name, namespace, _, _ := checkpoint.GetData() - return &runtimeapi.PodSandbox{ - Id: id, - Metadata: &runtimeapi.PodSandboxMetadata{ - Name: name, - Namespace: namespace, - }, - State: state, - } -} diff --git a/pkg/kubelet/dockershim/convert_test.go b/pkg/kubelet/dockershim/convert_test.go deleted file mode 100644 index f663fe0122d..00000000000 --- a/pkg/kubelet/dockershim/convert_test.go +++ /dev/null @@ -1,74 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "testing" - - dockertypes "github.com/docker/docker/api/types" - "github.com/stretchr/testify/assert" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -func TestConvertDockerStatusToRuntimeAPIState(t *testing.T) { - testCases := []struct { - input string - expected runtimeapi.ContainerState - }{ - {input: "Up 5 hours", expected: runtimeapi.ContainerState_CONTAINER_RUNNING}, - {input: "Exited (0) 2 hours ago", expected: runtimeapi.ContainerState_CONTAINER_EXITED}, - {input: "Created", expected: runtimeapi.ContainerState_CONTAINER_CREATED}, - {input: "Random string", expected: runtimeapi.ContainerState_CONTAINER_UNKNOWN}, - } - - for _, test := range testCases { - actual := toRuntimeAPIContainerState(test.input) - assert.Equal(t, test.expected, actual) - } -} - -func TestConvertToPullableImageID(t *testing.T) { - testCases := []struct { - id string - image *dockertypes.ImageInspect - expected string - }{ - { - id: "image-1", - image: &dockertypes.ImageInspect{ - RepoDigests: []string{"digest-1"}, - }, - expected: DockerPullableImageIDPrefix + "digest-1", - }, - { - id: "image-2", - image: &dockertypes.ImageInspect{ - RepoDigests: []string{}, - }, - expected: DockerImageIDPrefix + "image-2", - }, - } - - for _, test := range testCases { - actual := toPullableImageID(test.id, test.image) - assert.Equal(t, test.expected, actual) - } -} diff --git a/pkg/kubelet/dockershim/doc.go b/pkg/kubelet/dockershim/doc.go deleted file mode 100644 index e630364b2a8..00000000000 --- a/pkg/kubelet/dockershim/doc.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package dockershim implements a container runtime interface -// Docker integration using k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go -package dockershim diff --git a/pkg/kubelet/dockershim/docker_checkpoint.go b/pkg/kubelet/dockershim/docker_checkpoint.go deleted file mode 100644 index 37ac73050be..00000000000 --- a/pkg/kubelet/dockershim/docker_checkpoint.go +++ /dev/null @@ -1,109 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "encoding/json" - - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" -) - -const ( - // default directory to store pod sandbox checkpoint files - sandboxCheckpointDir = "sandbox" - protocolTCP = Protocol("tcp") - protocolUDP = Protocol("udp") - protocolSCTP = Protocol("sctp") - schemaVersion = "v1" -) - -// ContainerCheckpoint provides the interface for process container's checkpoint data -type ContainerCheckpoint interface { - checkpointmanager.Checkpoint - GetData() (string, string, string, []*PortMapping, bool) -} - -// Protocol is the type of port mapping protocol -type Protocol string - -// PortMapping is the port mapping configurations of a sandbox. -type PortMapping struct { - // Protocol of the port mapping. - Protocol *Protocol `json:"protocol,omitempty"` - // Port number within the container. - ContainerPort *int32 `json:"container_port,omitempty"` - // Port number on the host. - HostPort *int32 `json:"host_port,omitempty"` - // Host ip to expose. - HostIP string `json:"host_ip,omitempty"` -} - -// CheckpointData contains all types of data that can be stored in the checkpoint. -type CheckpointData struct { - PortMappings []*PortMapping `json:"port_mappings,omitempty"` - HostNetwork bool `json:"host_network,omitempty"` -} - -// PodSandboxCheckpoint is the checkpoint structure for a sandbox -type PodSandboxCheckpoint struct { - // Version of the pod sandbox checkpoint schema. - Version string `json:"version"` - // Pod name of the sandbox. Same as the pod name in the Pod ObjectMeta. - Name string `json:"name"` - // Pod namespace of the sandbox. Same as the pod namespace in the Pod ObjectMeta. - Namespace string `json:"namespace"` - // Data to checkpoint for pod sandbox. - Data *CheckpointData `json:"data,omitempty"` - // Checksum is calculated with fnv hash of the checkpoint object with checksum field set to be zero - Checksum checksum.Checksum `json:"checksum"` -} - -// NewPodSandboxCheckpoint inits a PodSandboxCheckpoint with the given args -func NewPodSandboxCheckpoint(namespace, name string, data *CheckpointData) ContainerCheckpoint { - return &PodSandboxCheckpoint{ - Version: schemaVersion, - Namespace: namespace, - Name: name, - Data: data, - } -} - -// MarshalCheckpoint encodes the PodSandboxCheckpoint instance to a json object -func (cp *PodSandboxCheckpoint) MarshalCheckpoint() ([]byte, error) { - cp.Checksum = checksum.New(*cp.Data) - return json.Marshal(*cp) -} - -// UnmarshalCheckpoint decodes the blob data to the PodSandboxCheckpoint instance -func (cp *PodSandboxCheckpoint) UnmarshalCheckpoint(blob []byte) error { - return json.Unmarshal(blob, cp) -} - -// VerifyChecksum verifies whether the PodSandboxCheckpoint's data checksum is -// the same as calculated checksum -func (cp *PodSandboxCheckpoint) VerifyChecksum() error { - return cp.Checksum.Verify(*cp.Data) -} - -// GetData gets the PodSandboxCheckpoint's version and some net information -func (cp *PodSandboxCheckpoint) GetData() (string, string, string, []*PortMapping, bool) { - return cp.Version, cp.Name, cp.Namespace, cp.Data.PortMappings, cp.Data.HostNetwork -} diff --git a/pkg/kubelet/dockershim/docker_checkpoint_test.go b/pkg/kubelet/dockershim/docker_checkpoint_test.go deleted file mode 100644 index 0649e78b0d3..00000000000 --- a/pkg/kubelet/dockershim/docker_checkpoint_test.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestPodSandboxCheckpoint(t *testing.T) { - data := &CheckpointData{HostNetwork: true} - checkpoint := NewPodSandboxCheckpoint("ns1", "sandbox1", data) - version, name, namespace, _, hostNetwork := checkpoint.GetData() - assert.Equal(t, schemaVersion, version) - assert.Equal(t, "ns1", namespace) - assert.Equal(t, "sandbox1", name) - assert.Equal(t, true, hostNetwork) -} diff --git a/pkg/kubelet/dockershim/docker_container.go b/pkg/kubelet/dockershim/docker_container.go deleted file mode 100644 index 8cc686d9885..00000000000 --- a/pkg/kubelet/dockershim/docker_container.go +++ /dev/null @@ -1,508 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "fmt" - "os" - "path/filepath" - "time" - - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - dockerfilters "github.com/docker/docker/api/types/filters" - dockerstrslice "github.com/docker/docker/api/types/strslice" - "k8s.io/klog/v2" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -// ListContainers lists all containers matching the filter. -func (ds *dockerService) ListContainers(_ context.Context, r *runtimeapi.ListContainersRequest) (*runtimeapi.ListContainersResponse, error) { - filter := r.GetFilter() - opts := dockertypes.ContainerListOptions{All: true} - - opts.Filters = dockerfilters.NewArgs() - f := newDockerFilter(&opts.Filters) - // Add filter to get *only* (non-sandbox) containers. - f.AddLabel(containerTypeLabelKey, containerTypeLabelContainer) - - if filter != nil { - if filter.Id != "" { - f.Add("id", filter.Id) - } - if filter.State != nil { - f.Add("status", toDockerContainerStatus(filter.GetState().State)) - } - if filter.PodSandboxId != "" { - f.AddLabel(sandboxIDLabelKey, filter.PodSandboxId) - } - - if filter.LabelSelector != nil { - for k, v := range filter.LabelSelector { - f.AddLabel(k, v) - } - } - } - containers, err := ds.client.ListContainers(opts) - if err != nil { - return nil, err - } - // Convert docker to runtime api containers. - result := []*runtimeapi.Container{} - for i := range containers { - c := containers[i] - - converted, err := toRuntimeAPIContainer(&c) - if err != nil { - klog.V(4).InfoS("Unable to convert docker to runtime API container", "err", err) - continue - } - - result = append(result, converted) - } - - return &runtimeapi.ListContainersResponse{Containers: result}, nil -} - -func (ds *dockerService) getContainerCleanupInfo(containerID string) (*containerCleanupInfo, bool) { - ds.cleanupInfosLock.RLock() - defer ds.cleanupInfosLock.RUnlock() - info, ok := ds.containerCleanupInfos[containerID] - return info, ok -} - -func (ds *dockerService) setContainerCleanupInfo(containerID string, info *containerCleanupInfo) { - ds.cleanupInfosLock.Lock() - defer ds.cleanupInfosLock.Unlock() - ds.containerCleanupInfos[containerID] = info -} - -func (ds *dockerService) clearContainerCleanupInfo(containerID string) { - ds.cleanupInfosLock.Lock() - defer ds.cleanupInfosLock.Unlock() - delete(ds.containerCleanupInfos, containerID) -} - -// CreateContainer creates a new container in the given PodSandbox -// Docker cannot store the log to an arbitrary location (yet), so we create an -// symlink at LogPath, linking to the actual path of the log. -// TODO: check if the default values returned by the runtime API are ok. -func (ds *dockerService) CreateContainer(_ context.Context, r *runtimeapi.CreateContainerRequest) (*runtimeapi.CreateContainerResponse, error) { - podSandboxID := r.PodSandboxId - config := r.GetConfig() - sandboxConfig := r.GetSandboxConfig() - - if config == nil { - return nil, fmt.Errorf("container config is nil") - } - if sandboxConfig == nil { - return nil, fmt.Errorf("sandbox config is nil for container %q", config.Metadata.Name) - } - - labels := makeLabels(config.GetLabels(), config.GetAnnotations()) - // Apply a the container type label. - labels[containerTypeLabelKey] = containerTypeLabelContainer - // Write the container log path in the labels. - labels[containerLogPathLabelKey] = filepath.Join(sandboxConfig.LogDirectory, config.LogPath) - // Write the sandbox ID in the labels. - labels[sandboxIDLabelKey] = podSandboxID - - apiVersion, err := ds.getDockerAPIVersion() - if err != nil { - return nil, fmt.Errorf("unable to get the docker API version: %v", err) - } - - image := "" - if iSpec := config.GetImage(); iSpec != nil { - image = iSpec.Image - } - containerName := makeContainerName(sandboxConfig, config) - createConfig := dockertypes.ContainerCreateConfig{ - Name: containerName, - Config: &dockercontainer.Config{ - // TODO: set User. - Entrypoint: dockerstrslice.StrSlice(config.Command), - Cmd: dockerstrslice.StrSlice(config.Args), - Env: generateEnvList(config.GetEnvs()), - Image: image, - WorkingDir: config.WorkingDir, - Labels: labels, - // Interactive containers: - OpenStdin: config.Stdin, - StdinOnce: config.StdinOnce, - Tty: config.Tty, - // Disable Docker's health check until we officially support it - // (https://github.com/kubernetes/kubernetes/issues/25829). - Healthcheck: &dockercontainer.HealthConfig{ - Test: []string{"NONE"}, - }, - }, - HostConfig: &dockercontainer.HostConfig{ - Binds: generateMountBindings(config.GetMounts()), - RestartPolicy: dockercontainer.RestartPolicy{ - Name: "no", - }, - }, - } - - hc := createConfig.HostConfig - err = ds.updateCreateConfig(&createConfig, config, sandboxConfig, podSandboxID, securityOptSeparator, apiVersion) - if err != nil { - return nil, fmt.Errorf("failed to update container create config: %v", err) - } - // Set devices for container. - devices := make([]dockercontainer.DeviceMapping, len(config.Devices)) - for i, device := range config.Devices { - devices[i] = dockercontainer.DeviceMapping{ - PathOnHost: device.HostPath, - PathInContainer: device.ContainerPath, - CgroupPermissions: device.Permissions, - } - } - hc.Resources.Devices = devices - - //nolint:staticcheck // SA1019 backwards compatibility - securityOpts, err := ds.getSecurityOpts(config.GetLinux().GetSecurityContext().GetSeccompProfilePath(), securityOptSeparator) - if err != nil { - return nil, fmt.Errorf("failed to generate security options for container %q: %v", config.Metadata.Name, err) - } - - hc.SecurityOpt = append(hc.SecurityOpt, securityOpts...) - - cleanupInfo, err := ds.applyPlatformSpecificDockerConfig(r, &createConfig) - if err != nil { - return nil, err - } - - createResp, createErr := ds.client.CreateContainer(createConfig) - if createErr != nil { - createResp, createErr = recoverFromCreationConflictIfNeeded(ds.client, createConfig, createErr) - } - - if createResp != nil { - containerID := createResp.ID - - if cleanupInfo != nil { - // we don't perform the clean up just yet at that could destroy information - // needed for the container to start (e.g. Windows credentials stored in - // registry keys); instead, we'll clean up when the container gets removed - ds.setContainerCleanupInfo(containerID, cleanupInfo) - } - return &runtimeapi.CreateContainerResponse{ContainerId: containerID}, nil - } - - // the creation failed, let's clean up right away - we ignore any errors though, - // this is best effort - ds.performPlatformSpecificContainerCleanupAndLogErrors(containerName, cleanupInfo) - - return nil, createErr -} - -// getContainerLogPath returns the container log path specified by kubelet and the real -// path where docker stores the container log. -func (ds *dockerService) getContainerLogPath(containerID string) (string, string, error) { - info, err := ds.client.InspectContainer(containerID) - if err != nil { - return "", "", fmt.Errorf("failed to inspect container %q: %v", containerID, err) - } - return info.Config.Labels[containerLogPathLabelKey], info.LogPath, nil -} - -// createContainerLogSymlink creates the symlink for docker container log. -func (ds *dockerService) createContainerLogSymlink(containerID string) error { - path, realPath, err := ds.getContainerLogPath(containerID) - if err != nil { - return fmt.Errorf("failed to get container %q log path: %v", containerID, err) - } - - if path == "" { - klog.V(5).InfoS("Container log path isn't specified, will not create the symlink", "containerID", containerID) - return nil - } - - if realPath != "" { - // Only create the symlink when container log path is specified and log file exists. - // Delete possibly existing file first - if err = ds.os.Remove(path); err == nil { - klog.InfoS("Deleted previously existing symlink file", "path", path) - } - if err = ds.os.Symlink(realPath, path); err != nil { - return fmt.Errorf("failed to create symbolic link %q to the container log file %q for container %q: %v", - path, realPath, containerID, err) - } - } else { - supported, err := ds.IsCRISupportedLogDriver() - if err != nil { - klog.InfoS("Failed to check supported logging driver by CRI", "err", err) - return nil - } - - if supported { - klog.InfoS("Cannot create symbolic link because container log file doesn't exist!") - } else { - klog.V(5).InfoS("Unsupported logging driver by CRI") - } - } - - return nil -} - -// removeContainerLogSymlink removes the symlink for docker container log. -func (ds *dockerService) removeContainerLogSymlink(containerID string) error { - path, _, err := ds.getContainerLogPath(containerID) - if err != nil { - return fmt.Errorf("failed to get container %q log path: %v", containerID, err) - } - if path != "" { - // Only remove the symlink when container log path is specified. - err := ds.os.Remove(path) - if err != nil && !os.IsNotExist(err) { - return fmt.Errorf("failed to remove container %q log symlink %q: %v", containerID, path, err) - } - } - return nil -} - -// StartContainer starts the container. -func (ds *dockerService) StartContainer(_ context.Context, r *runtimeapi.StartContainerRequest) (*runtimeapi.StartContainerResponse, error) { - err := ds.client.StartContainer(r.ContainerId) - - // Create container log symlink for all containers (including failed ones). - if linkError := ds.createContainerLogSymlink(r.ContainerId); linkError != nil { - // Do not stop the container if we failed to create symlink because: - // 1. This is not a critical failure. - // 2. We don't have enough information to properly stop container here. - // Kubelet will surface this error to user via an event. - return nil, linkError - } - - if err != nil { - err = transformStartContainerError(err) - return nil, fmt.Errorf("failed to start container %q: %v", r.ContainerId, err) - } - - return &runtimeapi.StartContainerResponse{}, nil -} - -// StopContainer stops a running container with a grace period (i.e., timeout). -func (ds *dockerService) StopContainer(_ context.Context, r *runtimeapi.StopContainerRequest) (*runtimeapi.StopContainerResponse, error) { - err := ds.client.StopContainer(r.ContainerId, time.Duration(r.Timeout)*time.Second) - if err != nil { - return nil, err - } - return &runtimeapi.StopContainerResponse{}, nil -} - -// RemoveContainer removes the container. -func (ds *dockerService) RemoveContainer(_ context.Context, r *runtimeapi.RemoveContainerRequest) (*runtimeapi.RemoveContainerResponse, error) { - // Ideally, log lifecycle should be independent of container lifecycle. - // However, docker will remove container log after container is removed, - // we can't prevent that now, so we also clean up the symlink here. - err := ds.removeContainerLogSymlink(r.ContainerId) - if err != nil { - return nil, err - } - errors := ds.performPlatformSpecificContainerForContainer(r.ContainerId) - if len(errors) != 0 { - return nil, fmt.Errorf("failed to run platform-specific clean ups for container %q: %v", r.ContainerId, errors) - } - err = ds.client.RemoveContainer(r.ContainerId, dockertypes.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) - if err != nil { - return nil, fmt.Errorf("failed to remove container %q: %v", r.ContainerId, err) - } - - return &runtimeapi.RemoveContainerResponse{}, nil -} - -func getContainerTimestamps(r *dockertypes.ContainerJSON) (time.Time, time.Time, time.Time, error) { - var createdAt, startedAt, finishedAt time.Time - var err error - - createdAt, err = libdocker.ParseDockerTimestamp(r.Created) - if err != nil { - return createdAt, startedAt, finishedAt, err - } - startedAt, err = libdocker.ParseDockerTimestamp(r.State.StartedAt) - if err != nil { - return createdAt, startedAt, finishedAt, err - } - finishedAt, err = libdocker.ParseDockerTimestamp(r.State.FinishedAt) - if err != nil { - return createdAt, startedAt, finishedAt, err - } - return createdAt, startedAt, finishedAt, nil -} - -// ContainerStatus inspects the docker container and returns the status. -func (ds *dockerService) ContainerStatus(_ context.Context, req *runtimeapi.ContainerStatusRequest) (*runtimeapi.ContainerStatusResponse, error) { - containerID := req.ContainerId - r, err := ds.client.InspectContainer(containerID) - if err != nil { - return nil, err - } - - // Parse the timestamps. - createdAt, startedAt, finishedAt, err := getContainerTimestamps(r) - if err != nil { - return nil, fmt.Errorf("failed to parse timestamp for container %q: %v", containerID, err) - } - - // Convert the image id to a pullable id. - ir, err := ds.client.InspectImageByID(r.Image) - if err != nil { - if !libdocker.IsImageNotFoundError(err) { - return nil, fmt.Errorf("unable to inspect docker image %q while inspecting docker container %q: %v", r.Image, containerID, err) - } - klog.InfoS("Ignore error image not found while inspecting docker container", "containerID", containerID, "image", r.Image, "err", err) - } - imageID := toPullableImageID(r.Image, ir) - - // Convert the mounts. - mounts := make([]*runtimeapi.Mount, 0, len(r.Mounts)) - for i := range r.Mounts { - m := r.Mounts[i] - readonly := !m.RW - mounts = append(mounts, &runtimeapi.Mount{ - HostPath: m.Source, - ContainerPath: m.Destination, - Readonly: readonly, - // Note: Can't set SeLinuxRelabel - }) - } - // Interpret container states and convert time to unix timestamps. - var state runtimeapi.ContainerState - var reason, message string - ct, st, ft := createdAt.UnixNano(), int64(0), int64(0) - if r.State.Running { - // Container is running. - state = runtimeapi.ContainerState_CONTAINER_RUNNING - // If container is not in the exited state, not set finished timestamp - st = startedAt.UnixNano() - } else { - // Container is *not* running. We need to get more details. - // * Case 1: container has run and exited with non-zero finishedAt - // time. - // * Case 2: container has failed to start; it has a zero finishedAt - // time, but a non-zero exit code. - // * Case 3: container has been created, but not started (yet). - if !finishedAt.IsZero() { // Case 1 - state = runtimeapi.ContainerState_CONTAINER_EXITED - st, ft = startedAt.UnixNano(), finishedAt.UnixNano() - switch { - case r.State.OOMKilled: - // TODO: consider exposing OOMKilled via the runtimeAPI. - // Note: if an application handles OOMKilled gracefully, the - // exit code could be zero. - reason = "OOMKilled" - case r.State.ExitCode == 0: - reason = "Completed" - default: - reason = "Error" - } - } else if r.State.ExitCode != 0 { // Case 2 - state = runtimeapi.ContainerState_CONTAINER_EXITED - // Adjust finished and started timestamp to createdAt time to avoid - // the confusion. - st, ft = createdAt.UnixNano(), createdAt.UnixNano() - reason = "ContainerCannotRun" - } else { // Case 3 - state = runtimeapi.ContainerState_CONTAINER_CREATED - } - message = r.State.Error - } - exitCode := int32(r.State.ExitCode) - - metadata, err := parseContainerName(r.Name) - if err != nil { - return nil, err - } - - labels, annotations := extractLabels(r.Config.Labels) - imageName := r.Config.Image - if ir != nil && len(ir.RepoTags) > 0 { - imageName = ir.RepoTags[0] - } - status := &runtimeapi.ContainerStatus{ - Id: r.ID, - Metadata: metadata, - Image: &runtimeapi.ImageSpec{Image: imageName}, - ImageRef: imageID, - Mounts: mounts, - ExitCode: exitCode, - State: state, - CreatedAt: ct, - StartedAt: st, - FinishedAt: ft, - Reason: reason, - Message: message, - Labels: labels, - Annotations: annotations, - LogPath: r.Config.Labels[containerLogPathLabelKey], - } - return &runtimeapi.ContainerStatusResponse{Status: status}, nil -} - -func (ds *dockerService) UpdateContainerResources(_ context.Context, r *runtimeapi.UpdateContainerResourcesRequest) (*runtimeapi.UpdateContainerResourcesResponse, error) { - resources := r.Linux - updateConfig := dockercontainer.UpdateConfig{ - Resources: dockercontainer.Resources{ - CPUPeriod: resources.CpuPeriod, - CPUQuota: resources.CpuQuota, - CPUShares: resources.CpuShares, - Memory: resources.MemoryLimitInBytes, - CpusetCpus: resources.CpusetCpus, - CpusetMems: resources.CpusetMems, - }, - } - - err := ds.client.UpdateContainerResources(r.ContainerId, updateConfig) - if err != nil { - return nil, fmt.Errorf("failed to update container %q: %v", r.ContainerId, err) - } - return &runtimeapi.UpdateContainerResourcesResponse{}, nil -} - -func (ds *dockerService) performPlatformSpecificContainerForContainer(containerID string) (errors []error) { - if cleanupInfo, present := ds.getContainerCleanupInfo(containerID); present { - errors = ds.performPlatformSpecificContainerCleanupAndLogErrors(containerID, cleanupInfo) - - if len(errors) == 0 { - ds.clearContainerCleanupInfo(containerID) - } - } - - return -} - -func (ds *dockerService) performPlatformSpecificContainerCleanupAndLogErrors(containerNameOrID string, cleanupInfo *containerCleanupInfo) []error { - if cleanupInfo == nil { - return nil - } - - errors := ds.performPlatformSpecificContainerCleanup(cleanupInfo) - for _, err := range errors { - klog.InfoS("Error when cleaning up after container", "containerNameOrID", containerNameOrID, "err", err) - } - - return errors -} diff --git a/pkg/kubelet/dockershim/docker_container_test.go b/pkg/kubelet/dockershim/docker_container_test.go deleted file mode 100644 index 071864cbe1b..00000000000 --- a/pkg/kubelet/dockershim/docker_container_test.go +++ /dev/null @@ -1,370 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "fmt" - "path/filepath" - "strings" - "sync" - "testing" - "time" - - dockertypes "github.com/docker/docker/api/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" -) - -const ( - sandboxID = "sandboxid" - containerID = "containerid" -) - -// A helper to create a basic config. -func makeContainerConfig(sConfig *runtimeapi.PodSandboxConfig, name, image string, attempt uint32, labels, annotations map[string]string) *runtimeapi.ContainerConfig { - return &runtimeapi.ContainerConfig{ - Metadata: &runtimeapi.ContainerMetadata{ - Name: name, - Attempt: attempt, - }, - Image: &runtimeapi.ImageSpec{Image: image}, - Labels: labels, - Annotations: annotations, - } -} - -func getTestCTX() context.Context { - return context.Background() -} - -// TestConcurrentlyCreateAndDeleteContainers is a regression test for #93771, which ensures -// kubelet would not panic on concurrent writes to `dockerService.containerCleanupInfos`. -func TestConcurrentlyCreateAndDeleteContainers(t *testing.T) { - ds, _, _ := newTestDockerService() - podName, namespace := "foo", "bar" - containerName, image := "sidecar", "logger" - - const count = 20 - configs := make([]*runtimeapi.ContainerConfig, 0, count) - sConfigs := make([]*runtimeapi.PodSandboxConfig, 0, count) - for i := 0; i < count; i++ { - s := makeSandboxConfig(fmt.Sprintf("%s%d", podName, i), - fmt.Sprintf("%s%d", namespace, i), fmt.Sprintf("%d", i), 0) - labels := map[string]string{"concurrent-test": fmt.Sprintf("label%d", i)} - c := makeContainerConfig(s, fmt.Sprintf("%s%d", containerName, i), - fmt.Sprintf("%s:v%d", image, i), uint32(i), labels, nil) - sConfigs = append(sConfigs, s) - configs = append(configs, c) - } - - containerIDs := make(chan string, len(configs)) // make channel non-blocking to simulate concurrent containers creation - - var ( - creationWg sync.WaitGroup - deletionWg sync.WaitGroup - ) - - creationWg.Add(len(configs)) - - go func() { - creationWg.Wait() - close(containerIDs) - }() - for i := range configs { - go func(i int) { - defer creationWg.Done() - // We don't care about the sandbox id; pass a bogus one. - sandboxID := fmt.Sprintf("sandboxid%d", i) - req := &runtimeapi.CreateContainerRequest{PodSandboxId: sandboxID, Config: configs[i], SandboxConfig: sConfigs[i]} - createResp, err := ds.CreateContainer(getTestCTX(), req) - if err != nil { - t.Errorf("CreateContainer: %v", err) - return - } - containerIDs <- createResp.ContainerId - }(i) - } - - for containerID := range containerIDs { - deletionWg.Add(1) - go func(id string) { - defer deletionWg.Done() - _, err := ds.RemoveContainer(getTestCTX(), &runtimeapi.RemoveContainerRequest{ContainerId: id}) - if err != nil { - t.Errorf("RemoveContainer: %v", err) - } - }(containerID) - } - deletionWg.Wait() -} - -// TestListContainers creates several containers and then list them to check -// whether the correct metadatas, states, and labels are returned. -func TestListContainers(t *testing.T) { - ds, _, fakeClock := newTestDockerService() - podName, namespace := "foo", "bar" - containerName, image := "sidecar", "logger" - - configs := []*runtimeapi.ContainerConfig{} - sConfigs := []*runtimeapi.PodSandboxConfig{} - for i := 0; i < 3; i++ { - s := makeSandboxConfig(fmt.Sprintf("%s%d", podName, i), - fmt.Sprintf("%s%d", namespace, i), fmt.Sprintf("%d", i), 0) - labels := map[string]string{"abc.xyz": fmt.Sprintf("label%d", i)} - annotations := map[string]string{"foo.bar.baz": fmt.Sprintf("annotation%d", i)} - c := makeContainerConfig(s, fmt.Sprintf("%s%d", containerName, i), - fmt.Sprintf("%s:v%d", image, i), uint32(i), labels, annotations) - sConfigs = append(sConfigs, s) - configs = append(configs, c) - } - - expected := []*runtimeapi.Container{} - state := runtimeapi.ContainerState_CONTAINER_RUNNING - var createdAt int64 = fakeClock.Now().UnixNano() - for i := range configs { - // We don't care about the sandbox id; pass a bogus one. - sandboxID := fmt.Sprintf("sandboxid%d", i) - req := &runtimeapi.CreateContainerRequest{PodSandboxId: sandboxID, Config: configs[i], SandboxConfig: sConfigs[i]} - createResp, err := ds.CreateContainer(getTestCTX(), req) - require.NoError(t, err) - id := createResp.ContainerId - _, err = ds.StartContainer(getTestCTX(), &runtimeapi.StartContainerRequest{ContainerId: id}) - require.NoError(t, err) - - imageRef := "" // FakeDockerClient doesn't populate ImageRef yet. - // Prepend to the expected list because ListContainers returns - // the most recent containers first. - expected = append([]*runtimeapi.Container{{ - Metadata: configs[i].Metadata, - Id: id, - PodSandboxId: sandboxID, - State: state, - CreatedAt: createdAt, - Image: configs[i].Image, - ImageRef: imageRef, - Labels: configs[i].Labels, - Annotations: configs[i].Annotations, - }}, expected...) - } - listResp, err := ds.ListContainers(getTestCTX(), &runtimeapi.ListContainersRequest{}) - require.NoError(t, err) - assert.Len(t, listResp.Containers, len(expected)) - assert.Equal(t, expected, listResp.Containers) -} - -// TestContainerStatus tests the basic lifecycle operations and verify that -// the status returned reflects the operations performed. -func TestContainerStatus(t *testing.T) { - ds, fDocker, fClock := newTestDockerService() - sConfig := makeSandboxConfig("foo", "bar", "1", 0) - labels := map[string]string{"abc.xyz": "foo"} - annotations := map[string]string{"foo.bar.baz": "abc"} - imageName := "iamimage" - config := makeContainerConfig(sConfig, "pause", imageName, 0, labels, annotations) - - state := runtimeapi.ContainerState_CONTAINER_CREATED - imageRef := DockerImageIDPrefix + imageName - // The following variables are not set in FakeDockerClient. - exitCode := int32(0) - var reason, message string - - expected := &runtimeapi.ContainerStatus{ - State: state, - Metadata: config.Metadata, - Image: config.Image, - ImageRef: imageRef, - ExitCode: exitCode, - Reason: reason, - Message: message, - Mounts: []*runtimeapi.Mount{}, - Labels: config.Labels, - Annotations: config.Annotations, - } - - fDocker.InjectImages([]dockertypes.ImageSummary{{ID: imageName}}) - - // Create the container. - fClock.SetTime(time.Now().Add(-1 * time.Hour)) - expected.CreatedAt = fClock.Now().UnixNano() - - req := &runtimeapi.CreateContainerRequest{PodSandboxId: sandboxID, Config: config, SandboxConfig: sConfig} - createResp, err := ds.CreateContainer(getTestCTX(), req) - require.NoError(t, err) - id := createResp.ContainerId - - // Check internal labels - c, err := fDocker.InspectContainer(id) - require.NoError(t, err) - assert.Equal(t, c.Config.Labels[containerTypeLabelKey], containerTypeLabelContainer) - assert.Equal(t, c.Config.Labels[sandboxIDLabelKey], sandboxID) - - // Set the id manually since we don't know the id until it's created. - expected.Id = id - assert.NoError(t, err) - resp, err := ds.ContainerStatus(getTestCTX(), &runtimeapi.ContainerStatusRequest{ContainerId: id}) - require.NoError(t, err) - assert.Equal(t, expected, resp.Status) - - // Advance the clock and start the container. - fClock.SetTime(time.Now()) - expected.StartedAt = fClock.Now().UnixNano() - expected.State = runtimeapi.ContainerState_CONTAINER_RUNNING - - _, err = ds.StartContainer(getTestCTX(), &runtimeapi.StartContainerRequest{ContainerId: id}) - require.NoError(t, err) - - resp, err = ds.ContainerStatus(getTestCTX(), &runtimeapi.ContainerStatusRequest{ContainerId: id}) - require.NoError(t, err) - assert.Equal(t, expected, resp.Status) - - // Advance the clock and stop the container. - fClock.SetTime(time.Now().Add(1 * time.Hour)) - expected.FinishedAt = fClock.Now().UnixNano() - expected.State = runtimeapi.ContainerState_CONTAINER_EXITED - expected.Reason = "Completed" - - _, err = ds.StopContainer(getTestCTX(), &runtimeapi.StopContainerRequest{ContainerId: id, Timeout: int64(0)}) - assert.NoError(t, err) - resp, err = ds.ContainerStatus(getTestCTX(), &runtimeapi.ContainerStatusRequest{ContainerId: id}) - require.NoError(t, err) - assert.Equal(t, expected, resp.Status) - - // Remove the container. - _, err = ds.RemoveContainer(getTestCTX(), &runtimeapi.RemoveContainerRequest{ContainerId: id}) - require.NoError(t, err) - resp, err = ds.ContainerStatus(getTestCTX(), &runtimeapi.ContainerStatusRequest{ContainerId: id}) - assert.Error(t, err, fmt.Sprintf("status of container: %+v", resp)) -} - -// TestContainerLogPath tests the container log creation logic. -func TestContainerLogPath(t *testing.T) { - ds, fDocker, _ := newTestDockerService() - podLogPath := "/pod/1" - containerLogPath := "0" - kubeletContainerLogPath := filepath.Join(podLogPath, containerLogPath) - sConfig := makeSandboxConfig("foo", "bar", "1", 0) - sConfig.LogDirectory = podLogPath - config := makeContainerConfig(sConfig, "pause", "iamimage", 0, nil, nil) - config.LogPath = containerLogPath - - req := &runtimeapi.CreateContainerRequest{PodSandboxId: sandboxID, Config: config, SandboxConfig: sConfig} - createResp, err := ds.CreateContainer(getTestCTX(), req) - require.NoError(t, err) - id := createResp.ContainerId - - // Check internal container log label - c, err := fDocker.InspectContainer(id) - assert.NoError(t, err) - assert.Equal(t, c.Config.Labels[containerLogPathLabelKey], kubeletContainerLogPath) - - // Set docker container log path - dockerContainerLogPath := "/docker/container/log" - c.LogPath = dockerContainerLogPath - - // Verify container log symlink creation - fakeOS := ds.os.(*containertest.FakeOS) - fakeOS.SymlinkFn = func(oldname, newname string) error { - assert.Equal(t, dockerContainerLogPath, oldname) - assert.Equal(t, kubeletContainerLogPath, newname) - return nil - } - _, err = ds.StartContainer(getTestCTX(), &runtimeapi.StartContainerRequest{ContainerId: id}) - require.NoError(t, err) - - _, err = ds.StopContainer(getTestCTX(), &runtimeapi.StopContainerRequest{ContainerId: id, Timeout: int64(0)}) - require.NoError(t, err) - - // Verify container log symlink deletion - // symlink is also tentatively deleted at startup - _, err = ds.RemoveContainer(getTestCTX(), &runtimeapi.RemoveContainerRequest{ContainerId: id}) - require.NoError(t, err) - assert.Equal(t, []string{kubeletContainerLogPath, kubeletContainerLogPath}, fakeOS.Removes) -} - -// TestContainerCreationConflict tests the logic to work around docker container -// creation naming conflict bug. -func TestContainerCreationConflict(t *testing.T) { - sConfig := makeSandboxConfig("foo", "bar", "1", 0) - config := makeContainerConfig(sConfig, "pause", "iamimage", 0, map[string]string{}, map[string]string{}) - containerName := makeContainerName(sConfig, config) - conflictError := fmt.Errorf("Error response from daemon: Conflict. The name \"/%s\" is already in use by container %q. You have to remove (or rename) that container to be able to reuse that name", - containerName, containerID) - noContainerError := fmt.Errorf("Error response from daemon: No such container: %s", containerID) - randomError := fmt.Errorf("random error") - - for desc, test := range map[string]struct { - createError error - removeError error - expectError error - expectCalls []string - expectFields int - }{ - "no create error": { - expectCalls: []string{"create"}, - expectFields: 6, - }, - "random create error": { - createError: randomError, - expectError: randomError, - expectCalls: []string{"create"}, - }, - "conflict create error with successful remove": { - createError: conflictError, - expectError: conflictError, - expectCalls: []string{"create", "remove"}, - }, - "conflict create error with random remove error": { - createError: conflictError, - removeError: randomError, - expectError: conflictError, - expectCalls: []string{"create", "remove"}, - }, - "conflict create error with no such container remove error": { - createError: conflictError, - removeError: noContainerError, - expectCalls: []string{"create", "remove", "create"}, - expectFields: 7, - }, - } { - t.Logf("TestCase: %s", desc) - ds, fDocker, _ := newTestDockerService() - - if test.createError != nil { - fDocker.InjectError("create", test.createError) - } - if test.removeError != nil { - fDocker.InjectError("remove", test.removeError) - } - - req := &runtimeapi.CreateContainerRequest{PodSandboxId: sandboxID, Config: config, SandboxConfig: sConfig} - createResp, err := ds.CreateContainer(getTestCTX(), req) - require.Equal(t, test.expectError, err) - assert.NoError(t, fDocker.AssertCalls(test.expectCalls)) - if err == nil { - c, err := fDocker.InspectContainer(createResp.ContainerId) - assert.NoError(t, err) - assert.Len(t, strings.Split(c.Name, nameDelimiter), test.expectFields) - } - } -} diff --git a/pkg/kubelet/dockershim/docker_container_unsupported.go b/pkg/kubelet/dockershim/docker_container_unsupported.go deleted file mode 100644 index 597002bbe4d..00000000000 --- a/pkg/kubelet/dockershim/docker_container_unsupported.go +++ /dev/null @@ -1,48 +0,0 @@ -//go:build !windows && !dockerless -// +build !windows,!dockerless - -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - dockertypes "github.com/docker/docker/api/types" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -type containerCleanupInfo struct{} - -// applyPlatformSpecificDockerConfig applies platform-specific configurations to a dockertypes.ContainerCreateConfig struct. -// The containerCleanupInfo struct it returns will be passed as is to performPlatformSpecificContainerCleanup -// after either the container creation has failed or the container has been removed. -func (ds *dockerService) applyPlatformSpecificDockerConfig(*runtimeapi.CreateContainerRequest, *dockertypes.ContainerCreateConfig) (*containerCleanupInfo, error) { - return nil, nil -} - -// performPlatformSpecificContainerCleanup is responsible for doing any platform-specific cleanup -// after either the container creation has failed or the container has been removed. -func (ds *dockerService) performPlatformSpecificContainerCleanup(cleanupInfo *containerCleanupInfo) (errors []error) { - return -} - -// platformSpecificContainerInitCleanup is called when dockershim -// is starting, and is meant to clean up any cruft left by previous runs -// creating containers. -// Errors are simply logged, but don't prevent dockershim from starting. -func (ds *dockerService) platformSpecificContainerInitCleanup() (errors []error) { - return -} diff --git a/pkg/kubelet/dockershim/docker_container_windows.go b/pkg/kubelet/dockershim/docker_container_windows.go deleted file mode 100644 index e76b4fd3080..00000000000 --- a/pkg/kubelet/dockershim/docker_container_windows.go +++ /dev/null @@ -1,218 +0,0 @@ -//go:build windows && !dockerless -// +build windows,!dockerless - -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "crypto/rand" - "encoding/hex" - "fmt" - "regexp" - - "golang.org/x/sys/windows/registry" - - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -type containerCleanupInfo struct { - gMSARegistryValueName string -} - -// applyPlatformSpecificDockerConfig applies platform-specific configurations to a dockertypes.ContainerCreateConfig struct. -// The containerCleanupInfo struct it returns will be passed as is to performPlatformSpecificContainerCleanup -// after either the container creation has failed or the container has been removed. -func (ds *dockerService) applyPlatformSpecificDockerConfig(request *runtimeapi.CreateContainerRequest, createConfig *dockertypes.ContainerCreateConfig) (*containerCleanupInfo, error) { - cleanupInfo := &containerCleanupInfo{} - - if err := applyGMSAConfig(request.GetConfig(), createConfig, cleanupInfo); err != nil { - return nil, err - } - - return cleanupInfo, nil -} - -// applyGMSAConfig looks at the container's .Windows.SecurityContext.GMSACredentialSpec field; if present, -// it copies its contents to a unique registry value, and sets a SecurityOpt on the config pointing to that registry value. -// We use registry values instead of files since their location cannot change - as opposed to credential spec files, -// whose location could potentially change down the line, or even be unknown (eg if docker is not installed on the -// C: drive) -// When docker supports passing a credential spec's contents directly, we should switch to using that -// as it will avoid cluttering the registry - there is a moby PR out for this: -// https://github.com/moby/moby/pull/38777 -func applyGMSAConfig(config *runtimeapi.ContainerConfig, createConfig *dockertypes.ContainerCreateConfig, cleanupInfo *containerCleanupInfo) error { - var credSpec string - if config.Windows != nil && config.Windows.SecurityContext != nil { - credSpec = config.Windows.SecurityContext.CredentialSpec - } - if credSpec == "" { - return nil - } - - valueName, err := copyGMSACredSpecToRegistryValue(credSpec) - if err != nil { - return err - } - - if createConfig.HostConfig == nil { - createConfig.HostConfig = &dockercontainer.HostConfig{} - } - - createConfig.HostConfig.SecurityOpt = append(createConfig.HostConfig.SecurityOpt, "credentialspec=registry://"+valueName) - cleanupInfo.gMSARegistryValueName = valueName - - return nil -} - -const ( - // same as https://github.com/moby/moby/blob/93d994e29c9cc8d81f1b0477e28d705fa7e2cd72/daemon/oci_windows.go#L23 - credentialSpecRegistryLocation = `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs` - // the prefix for the registry values we write GMSA cred specs to - gMSARegistryValueNamePrefix = "k8s-cred-spec-" - // the number of random bytes to generate suffixes for registry value names - gMSARegistryValueNameSuffixRandomBytes = 40 -) - -// registryKey is an interface wrapper around `registry.Key`, -// listing only the methods we care about here. -// It's mainly useful to easily allow mocking the registry in tests. -type registryKey interface { - SetStringValue(name, value string) error - DeleteValue(name string) error - ReadValueNames(n int) ([]string, error) - Close() error -} - -var registryCreateKeyFunc = func(baseKey registry.Key, path string, access uint32) (registryKey, bool, error) { - return registry.CreateKey(baseKey, path, access) -} - -// randomReader is only meant to ever be overridden for testing purposes, -// same idea as for `registryKey` above -var randomReader = rand.Reader - -// gMSARegistryValueNamesRegex is the regex used to detect gMSA cred spec -// registry values in `removeAllGMSARegistryValues` below. -var gMSARegistryValueNamesRegex = regexp.MustCompile(fmt.Sprintf("^%s[0-9a-f]{%d}$", gMSARegistryValueNamePrefix, 2*gMSARegistryValueNameSuffixRandomBytes)) - -// copyGMSACredSpecToRegistryKey copies the credential specs to a unique registry value, and returns its name. -func copyGMSACredSpecToRegistryValue(credSpec string) (string, error) { - valueName, err := gMSARegistryValueName() - if err != nil { - return "", err - } - - // write to the registry - key, _, err := registryCreateKeyFunc(registry.LOCAL_MACHINE, credentialSpecRegistryLocation, registry.SET_VALUE) - if err != nil { - return "", fmt.Errorf("unable to open registry key %q: %v", credentialSpecRegistryLocation, err) - } - defer key.Close() - if err = key.SetStringValue(valueName, credSpec); err != nil { - return "", fmt.Errorf("unable to write into registry value %q/%q: %v", credentialSpecRegistryLocation, valueName, err) - } - - return valueName, nil -} - -// gMSARegistryValueName computes the name of the registry value where to store the GMSA cred spec contents. -// The value's name is a purely random suffix appended to `gMSARegistryValueNamePrefix`. -func gMSARegistryValueName() (string, error) { - randomSuffix, err := randomString(gMSARegistryValueNameSuffixRandomBytes) - - if err != nil { - return "", fmt.Errorf("error when generating gMSA registry value name: %v", err) - } - - return gMSARegistryValueNamePrefix + randomSuffix, nil -} - -// randomString returns a random hex string. -func randomString(length int) (string, error) { - randBytes := make([]byte, length) - - if n, err := randomReader.Read(randBytes); err != nil || n != length { - if err == nil { - err = fmt.Errorf("only got %v random bytes, expected %v", n, length) - } - return "", fmt.Errorf("unable to generate random string: %v", err) - } - - return hex.EncodeToString(randBytes), nil -} - -// performPlatformSpecificContainerCleanup is responsible for doing any platform-specific cleanup -// after either the container creation has failed or the container has been removed. -func (ds *dockerService) performPlatformSpecificContainerCleanup(cleanupInfo *containerCleanupInfo) (errors []error) { - if err := removeGMSARegistryValue(cleanupInfo); err != nil { - errors = append(errors, err) - } - - return -} - -func removeGMSARegistryValue(cleanupInfo *containerCleanupInfo) error { - if cleanupInfo == nil || cleanupInfo.gMSARegistryValueName == "" { - return nil - } - - key, _, err := registryCreateKeyFunc(registry.LOCAL_MACHINE, credentialSpecRegistryLocation, registry.SET_VALUE) - if err != nil { - return fmt.Errorf("unable to open registry key %q: %v", credentialSpecRegistryLocation, err) - } - defer key.Close() - if err = key.DeleteValue(cleanupInfo.gMSARegistryValueName); err != nil { - return fmt.Errorf("unable to remove registry value %q/%q: %v", credentialSpecRegistryLocation, cleanupInfo.gMSARegistryValueName, err) - } - - return nil -} - -// platformSpecificContainerInitCleanup is called when dockershim -// is starting, and is meant to clean up any cruft left by previous runs -// creating containers. -// Errors are simply logged, but don't prevent dockershim from starting. -func (ds *dockerService) platformSpecificContainerInitCleanup() (errors []error) { - return removeAllGMSARegistryValues() -} - -func removeAllGMSARegistryValues() (errors []error) { - key, _, err := registryCreateKeyFunc(registry.LOCAL_MACHINE, credentialSpecRegistryLocation, registry.SET_VALUE) - if err != nil { - return []error{fmt.Errorf("unable to open registry key %q: %v", credentialSpecRegistryLocation, err)} - } - defer key.Close() - - valueNames, err := key.ReadValueNames(0) - if err != nil { - return []error{fmt.Errorf("unable to list values under registry key %q: %v", credentialSpecRegistryLocation, err)} - } - - for _, valueName := range valueNames { - if gMSARegistryValueNamesRegex.MatchString(valueName) { - if err = key.DeleteValue(valueName); err != nil { - errors = append(errors, fmt.Errorf("unable to remove registry value %q/%q: %v", credentialSpecRegistryLocation, valueName, err)) - } - } - } - - return -} diff --git a/pkg/kubelet/dockershim/docker_container_windows_test.go b/pkg/kubelet/dockershim/docker_container_windows_test.go deleted file mode 100644 index c7af2818774..00000000000 --- a/pkg/kubelet/dockershim/docker_container_windows_test.go +++ /dev/null @@ -1,311 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "bytes" - "fmt" - "regexp" - "testing" - - dockertypes "github.com/docker/docker/api/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/sys/windows/registry" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -type dummyRegistryKey struct { - setStringValueError error - setStringValueArgs [][]string - - deleteValueFunc func(name string) error - deleteValueArgs []string - - readValueNamesError error - readValueNamesReturn []string - readValueNamesArgs []int - - closed bool -} - -func (k *dummyRegistryKey) SetStringValue(name, value string) error { - k.setStringValueArgs = append(k.setStringValueArgs, []string{name, value}) - return k.setStringValueError -} - -func (k *dummyRegistryKey) DeleteValue(name string) error { - k.deleteValueArgs = append(k.deleteValueArgs, name) - if k.deleteValueFunc == nil { - return nil - } - return k.deleteValueFunc(name) -} - -func (k *dummyRegistryKey) ReadValueNames(n int) ([]string, error) { - k.readValueNamesArgs = append(k.readValueNamesArgs, n) - return k.readValueNamesReturn, k.readValueNamesError -} - -func (k *dummyRegistryKey) Close() error { - k.closed = true - return nil -} - -func TestApplyGMSAConfig(t *testing.T) { - dummyCredSpec := "test cred spec contents" - randomBytes := []byte{0x19, 0x0, 0x25, 0x45, 0x18, 0x52, 0x9e, 0x2a, 0x3d, 0xed, 0xb8, 0x5c, 0xde, 0xc0, 0x3c, 0xe2, 0x70, 0x55, 0x96, 0x47, 0x45, 0x9a, 0xb5, 0x31, 0xf0, 0x7a, 0xf5, 0xeb, 0x1c, 0x54, 0x95, 0xfd, 0xa7, 0x9, 0x43, 0x5c, 0xe8, 0x2a, 0xb8, 0x9c} - expectedHex := "1900254518529e2a3dedb85cdec03ce270559647459ab531f07af5eb1c5495fda709435ce82ab89c" - expectedValueName := "k8s-cred-spec-" + expectedHex - - containerConfigWithGMSAAnnotation := &runtimeapi.ContainerConfig{ - Windows: &runtimeapi.WindowsContainerConfig{ - SecurityContext: &runtimeapi.WindowsContainerSecurityContext{ - CredentialSpec: dummyCredSpec, - }, - }, - } - - t.Run("happy path", func(t *testing.T) { - key := &dummyRegistryKey{} - defer setRegistryCreateKeyFunc(t, key)() - defer setRandomReader(randomBytes)() - - createConfig := &dockertypes.ContainerCreateConfig{} - cleanupInfo := &containerCleanupInfo{} - err := applyGMSAConfig(containerConfigWithGMSAAnnotation, createConfig, cleanupInfo) - - assert.NoError(t, err) - - // the registry key should have been properly created - if assert.Equal(t, 1, len(key.setStringValueArgs)) { - assert.Equal(t, []string{expectedValueName, dummyCredSpec}, key.setStringValueArgs[0]) - } - assert.True(t, key.closed) - - // the create config's security opt should have been populated - if assert.NotNil(t, createConfig.HostConfig) { - assert.Equal(t, createConfig.HostConfig.SecurityOpt, []string{"credentialspec=registry://" + expectedValueName}) - } - - // and the name of that value should have been saved to the cleanup info - assert.Equal(t, expectedValueName, cleanupInfo.gMSARegistryValueName) - }) - t.Run("happy path with a truly random string", func(t *testing.T) { - defer setRegistryCreateKeyFunc(t, &dummyRegistryKey{})() - - createConfig := &dockertypes.ContainerCreateConfig{} - cleanupInfo := &containerCleanupInfo{} - err := applyGMSAConfig(containerConfigWithGMSAAnnotation, createConfig, cleanupInfo) - - assert.NoError(t, err) - - if assert.NotNil(t, createConfig.HostConfig) && assert.Equal(t, 1, len(createConfig.HostConfig.SecurityOpt)) { - secOpt := createConfig.HostConfig.SecurityOpt[0] - - expectedPrefix := "credentialspec=registry://k8s-cred-spec-" - assert.Equal(t, expectedPrefix, secOpt[:len(expectedPrefix)]) - - hex := secOpt[len(expectedPrefix):] - hexRegex := regexp.MustCompile("^[0-9a-f]{80}$") - assert.True(t, hexRegex.MatchString(hex)) - assert.NotEqual(t, expectedHex, hex) - - assert.Equal(t, "k8s-cred-spec-"+hex, cleanupInfo.gMSARegistryValueName) - } - }) - t.Run("when there's an error generating the random value name", func(t *testing.T) { - defer setRandomReader([]byte{})() - - err := applyGMSAConfig(containerConfigWithGMSAAnnotation, &dockertypes.ContainerCreateConfig{}, &containerCleanupInfo{}) - - require.Error(t, err) - assert.Contains(t, err.Error(), "error when generating gMSA registry value name: unable to generate random string") - }) - t.Run("if there's an error opening the registry key", func(t *testing.T) { - defer setRegistryCreateKeyFunc(t, &dummyRegistryKey{}, fmt.Errorf("dummy error"))() - - err := applyGMSAConfig(containerConfigWithGMSAAnnotation, &dockertypes.ContainerCreateConfig{}, &containerCleanupInfo{}) - - require.Error(t, err) - assert.Contains(t, err.Error(), "unable to open registry key") - }) - t.Run("if there's an error writing to the registry key", func(t *testing.T) { - key := &dummyRegistryKey{} - key.setStringValueError = fmt.Errorf("dummy error") - defer setRegistryCreateKeyFunc(t, key)() - - err := applyGMSAConfig(containerConfigWithGMSAAnnotation, &dockertypes.ContainerCreateConfig{}, &containerCleanupInfo{}) - - if assert.Error(t, err) { - assert.Contains(t, err.Error(), "unable to write into registry value") - } - assert.True(t, key.closed) - }) - t.Run("if there is no GMSA annotation", func(t *testing.T) { - createConfig := &dockertypes.ContainerCreateConfig{} - - err := applyGMSAConfig(&runtimeapi.ContainerConfig{}, createConfig, &containerCleanupInfo{}) - - assert.NoError(t, err) - assert.Nil(t, createConfig.HostConfig) - }) -} - -func TestRemoveGMSARegistryValue(t *testing.T) { - valueName := "k8s-cred-spec-1900254518529e2a3dedb85cdec03ce270559647459ab531f07af5eb1c5495fda709435ce82ab89c" - cleanupInfoWithValue := &containerCleanupInfo{gMSARegistryValueName: valueName} - - t.Run("it does remove the registry value", func(t *testing.T) { - key := &dummyRegistryKey{} - defer setRegistryCreateKeyFunc(t, key)() - - err := removeGMSARegistryValue(cleanupInfoWithValue) - - assert.NoError(t, err) - - // the registry key should have been properly deleted - if assert.Equal(t, 1, len(key.deleteValueArgs)) { - assert.Equal(t, []string{valueName}, key.deleteValueArgs) - } - assert.True(t, key.closed) - }) - t.Run("if there's an error opening the registry key", func(t *testing.T) { - defer setRegistryCreateKeyFunc(t, &dummyRegistryKey{}, fmt.Errorf("dummy error"))() - - err := removeGMSARegistryValue(cleanupInfoWithValue) - - require.Error(t, err) - assert.Contains(t, err.Error(), "unable to open registry key") - }) - t.Run("if there's an error deleting from the registry key", func(t *testing.T) { - key := &dummyRegistryKey{} - key.deleteValueFunc = func(name string) error { return fmt.Errorf("dummy error") } - defer setRegistryCreateKeyFunc(t, key)() - - err := removeGMSARegistryValue(cleanupInfoWithValue) - - if assert.Error(t, err) { - assert.Contains(t, err.Error(), "unable to remove registry value") - } - assert.True(t, key.closed) - }) - t.Run("if there's no registry value to be removed, it does nothing", func(t *testing.T) { - key := &dummyRegistryKey{} - defer setRegistryCreateKeyFunc(t, key)() - - err := removeGMSARegistryValue(&containerCleanupInfo{}) - - assert.NoError(t, err) - assert.Equal(t, 0, len(key.deleteValueArgs)) - }) -} - -func TestRemoveAllGMSARegistryValues(t *testing.T) { - cred1 := "k8s-cred-spec-1900254518529e2a3dedb85cdec03ce270559647459ab531f07af5eb1c5495fda709435ce82ab89c" - cred2 := "k8s-cred-spec-8891436007c795a904fdf77b5348e94305e4c48c5f01c47e7f65e980dc7edda85f112715891d65fd" - cred3 := "k8s-cred-spec-2f11f1c9e4f8182fe13caa708bd42b2098c8eefc489d6cc98806c058ccbe4cb3703b9ade61ce59a1" - cred4 := "k8s-cred-spec-dc532f189598a8220a1e538f79081eee979f94fbdbf8d37e36959485dee57157c03742d691e1fae2" - - t.Run("it removes the keys matching the k8s creds pattern", func(t *testing.T) { - key := &dummyRegistryKey{readValueNamesReturn: []string{cred1, "other_creds", cred2}} - defer setRegistryCreateKeyFunc(t, key)() - - errors := removeAllGMSARegistryValues() - - assert.Equal(t, 0, len(errors)) - assert.Equal(t, []string{cred1, cred2}, key.deleteValueArgs) - assert.Equal(t, []int{0}, key.readValueNamesArgs) - assert.True(t, key.closed) - }) - t.Run("it ignores errors and does a best effort at removing all k8s creds", func(t *testing.T) { - key := &dummyRegistryKey{ - readValueNamesReturn: []string{cred1, cred2, cred3, cred4}, - deleteValueFunc: func(name string) error { - if name == cred1 || name == cred3 { - return fmt.Errorf("dummy error") - } - return nil - }, - } - defer setRegistryCreateKeyFunc(t, key)() - - errors := removeAllGMSARegistryValues() - - assert.Equal(t, 2, len(errors)) - for _, err := range errors { - assert.Contains(t, err.Error(), "unable to remove registry value") - } - assert.Equal(t, []string{cred1, cred2, cred3, cred4}, key.deleteValueArgs) - assert.Equal(t, []int{0}, key.readValueNamesArgs) - assert.True(t, key.closed) - }) - t.Run("if there's an error opening the registry key", func(t *testing.T) { - defer setRegistryCreateKeyFunc(t, &dummyRegistryKey{}, fmt.Errorf("dummy error"))() - - errors := removeAllGMSARegistryValues() - - require.Equal(t, 1, len(errors)) - assert.Contains(t, errors[0].Error(), "unable to open registry key") - }) - t.Run("if it's unable to list the registry values", func(t *testing.T) { - key := &dummyRegistryKey{readValueNamesError: fmt.Errorf("dummy error")} - defer setRegistryCreateKeyFunc(t, key)() - - errors := removeAllGMSARegistryValues() - - if assert.Equal(t, 1, len(errors)) { - assert.Contains(t, errors[0].Error(), "unable to list values under registry key") - } - assert.True(t, key.closed) - }) -} - -// setRegistryCreateKeyFunc replaces the registryCreateKeyFunc package variable, and returns a function -// to be called to revert the change when done with testing. -func setRegistryCreateKeyFunc(t *testing.T, key *dummyRegistryKey, err ...error) func() { - previousRegistryCreateKeyFunc := registryCreateKeyFunc - - registryCreateKeyFunc = func(baseKey registry.Key, path string, access uint32) (registryKey, bool, error) { - // this should always be called with exactly the same arguments - assert.Equal(t, registry.LOCAL_MACHINE, baseKey) - assert.Equal(t, credentialSpecRegistryLocation, path) - assert.Equal(t, uint32(registry.SET_VALUE), access) - - if len(err) > 0 { - return nil, false, err[0] - } - return key, false, nil - } - - return func() { - registryCreateKeyFunc = previousRegistryCreateKeyFunc - } -} - -// setRandomReader replaces the randomReader package variable with a dummy reader that returns the provided -// byte slice, and returns a function to be called to revert the change when done with testing. -func setRandomReader(b []byte) func() { - previousRandomReader := randomReader - randomReader = bytes.NewReader(b) - return func() { - randomReader = previousRandomReader - } -} diff --git a/pkg/kubelet/dockershim/docker_image.go b/pkg/kubelet/dockershim/docker_image.go deleted file mode 100644 index 1982adedbd0..00000000000 --- a/pkg/kubelet/dockershim/docker_image.go +++ /dev/null @@ -1,192 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "fmt" - "net/http" - - dockertypes "github.com/docker/docker/api/types" - dockerfilters "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/pkg/jsonmessage" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/klog/v2" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -// This file implements methods in ImageManagerService. - -// ListImages lists existing images. -func (ds *dockerService) ListImages(_ context.Context, r *runtimeapi.ListImagesRequest) (*runtimeapi.ListImagesResponse, error) { - filter := r.GetFilter() - opts := dockertypes.ImageListOptions{} - if filter != nil { - if filter.GetImage().GetImage() != "" { - opts.Filters = dockerfilters.NewArgs() - opts.Filters.Add("reference", filter.GetImage().GetImage()) - } - } - - images, err := ds.client.ListImages(opts) - if err != nil { - return nil, err - } - - result := make([]*runtimeapi.Image, 0, len(images)) - for _, i := range images { - apiImage, err := imageToRuntimeAPIImage(&i) - if err != nil { - klog.V(5).InfoS("Failed to convert docker API image to runtime API image", "image", i, "err", err) - continue - } - result = append(result, apiImage) - } - return &runtimeapi.ListImagesResponse{Images: result}, nil -} - -// ImageStatus returns the status of the image, returns nil if the image doesn't present. -func (ds *dockerService) ImageStatus(_ context.Context, r *runtimeapi.ImageStatusRequest) (*runtimeapi.ImageStatusResponse, error) { - image := r.GetImage() - - imageInspect, err := ds.client.InspectImageByRef(image.Image) - if err != nil { - if !libdocker.IsImageNotFoundError(err) { - return nil, err - } - imageInspect, err = ds.client.InspectImageByID(image.Image) - if err != nil { - if libdocker.IsImageNotFoundError(err) { - return &runtimeapi.ImageStatusResponse{}, nil - } - return nil, err - } - } - - imageStatus, err := imageInspectToRuntimeAPIImage(imageInspect) - if err != nil { - return nil, err - } - - res := runtimeapi.ImageStatusResponse{Image: imageStatus} - if r.GetVerbose() { - res.Info = imageInspect.Config.Labels - } - return &res, nil -} - -// PullImage pulls an image with authentication config. -func (ds *dockerService) PullImage(_ context.Context, r *runtimeapi.PullImageRequest) (*runtimeapi.PullImageResponse, error) { - image := r.GetImage() - auth := r.GetAuth() - authConfig := dockertypes.AuthConfig{} - - if auth != nil { - authConfig.Username = auth.Username - authConfig.Password = auth.Password - authConfig.ServerAddress = auth.ServerAddress - authConfig.IdentityToken = auth.IdentityToken - authConfig.RegistryToken = auth.RegistryToken - } - err := ds.client.PullImage(image.Image, - authConfig, - dockertypes.ImagePullOptions{}, - ) - if err != nil { - return nil, filterHTTPError(err, image.Image) - } - - imageRef, err := getImageRef(ds.client, image.Image) - if err != nil { - return nil, err - } - - return &runtimeapi.PullImageResponse{ImageRef: imageRef}, nil -} - -// RemoveImage removes the image. -func (ds *dockerService) RemoveImage(_ context.Context, r *runtimeapi.RemoveImageRequest) (*runtimeapi.RemoveImageResponse, error) { - image := r.GetImage() - // If the image has multiple tags, we need to remove all the tags - // TODO: We assume image.Image is image ID here, which is true in the current implementation - // of kubelet, but we should still clarify this in CRI. - imageInspect, err := ds.client.InspectImageByID(image.Image) - - // dockerclient.InspectImageByID doesn't work with digest and repoTags, - // it is safe to continue removing it since there is another check below. - if err != nil && !libdocker.IsImageNotFoundError(err) { - return nil, err - } - - if imageInspect == nil { - // image is nil, assuming it doesn't exist. - return &runtimeapi.RemoveImageResponse{}, nil - } - - // An image can have different numbers of RepoTags and RepoDigests. - // Iterating over both of them plus the image ID ensures the image really got removed. - // It also prevents images from being deleted, which actually are deletable using this approach. - var images []string - images = append(images, imageInspect.RepoTags...) - images = append(images, imageInspect.RepoDigests...) - images = append(images, image.Image) - - for _, image := range images { - if _, err := ds.client.RemoveImage(image, dockertypes.ImageRemoveOptions{PruneChildren: true}); err != nil && !libdocker.IsImageNotFoundError(err) { - return nil, err - } - } - - return &runtimeapi.RemoveImageResponse{}, nil -} - -// getImageRef returns the image digest if exists, or else returns the image ID. -func getImageRef(client libdocker.Interface, image string) (string, error) { - img, err := client.InspectImageByRef(image) - if err != nil { - return "", err - } - if img == nil { - return "", fmt.Errorf("unable to inspect image %s", image) - } - - // Returns the digest if it exist. - if len(img.RepoDigests) > 0 { - return img.RepoDigests[0], nil - } - - return img.ID, nil -} - -func filterHTTPError(err error, image string) error { - // docker/docker/pull/11314 prints detailed error info for docker pull. - // When it hits 502, it returns a verbose html output including an inline svg, - // which makes the output of kubectl get pods much harder to parse. - // Here converts such verbose output to a concise one. - jerr, ok := err.(*jsonmessage.JSONError) - if ok && (jerr.Code == http.StatusBadGateway || - jerr.Code == http.StatusServiceUnavailable || - jerr.Code == http.StatusGatewayTimeout) { - return fmt.Errorf("RegistryUnavailable: %v", err) - } - return err - -} diff --git a/pkg/kubelet/dockershim/docker_image_linux.go b/pkg/kubelet/dockershim/docker_image_linux.go deleted file mode 100644 index ecd695d65db..00000000000 --- a/pkg/kubelet/dockershim/docker_image_linux.go +++ /dev/null @@ -1,70 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "os" - "path/filepath" - "time" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// ImageFsInfo returns information of the filesystem that is used to store images. -func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInfoRequest) (*runtimeapi.ImageFsInfoResponse, error) { - bytes, inodes, err := dirSize(filepath.Join(ds.dockerRootDir, "image")) - if err != nil { - return nil, err - } - - return &runtimeapi.ImageFsInfoResponse{ - ImageFilesystems: []*runtimeapi.FilesystemUsage{ - { - Timestamp: time.Now().Unix(), - FsId: &runtimeapi.FilesystemIdentifier{ - Mountpoint: ds.dockerRootDir, - }, - UsedBytes: &runtimeapi.UInt64Value{ - Value: uint64(bytes), - }, - InodesUsed: &runtimeapi.UInt64Value{ - Value: uint64(inodes), - }, - }, - }, - }, nil -} - -func dirSize(path string) (int64, int64, error) { - bytes := int64(0) - inodes := int64(0) - err := filepath.Walk(path, func(dir string, info os.FileInfo, err error) error { - if err != nil { - return err - } - inodes++ - if !info.IsDir() { - bytes += info.Size() - } - return nil - }) - return bytes, inodes, err -} diff --git a/pkg/kubelet/dockershim/docker_image_test.go b/pkg/kubelet/dockershim/docker_image_test.go deleted file mode 100644 index 5a0e15cc225..00000000000 --- a/pkg/kubelet/dockershim/docker_image_test.go +++ /dev/null @@ -1,113 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - "testing" - - dockertypes "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -func TestRemoveImage(t *testing.T) { - tests := map[string]struct { - image dockertypes.ImageInspect - calledDetails []libdocker.CalledDetail - }{ - "single tag": { - dockertypes.ImageInspect{ID: "1111", RepoTags: []string{"foo"}}, - []libdocker.CalledDetail{ - libdocker.NewCalledDetail("inspect_image", nil), - libdocker.NewCalledDetail("remove_image", []interface{}{"foo", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - libdocker.NewCalledDetail("remove_image", []interface{}{"1111", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - }, - }, - "multiple tags": { - dockertypes.ImageInspect{ID: "2222", RepoTags: []string{"foo", "bar"}}, - []libdocker.CalledDetail{ - libdocker.NewCalledDetail("inspect_image", nil), - libdocker.NewCalledDetail("remove_image", []interface{}{"foo", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - libdocker.NewCalledDetail("remove_image", []interface{}{"bar", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - libdocker.NewCalledDetail("remove_image", []interface{}{"2222", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - }, - }, - "single tag multiple repo digests": { - dockertypes.ImageInspect{ID: "3333", RepoTags: []string{"foo"}, RepoDigests: []string{"foo@3333", "example.com/foo@3333"}}, - []libdocker.CalledDetail{ - libdocker.NewCalledDetail("inspect_image", nil), - libdocker.NewCalledDetail("remove_image", []interface{}{"foo", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - libdocker.NewCalledDetail("remove_image", []interface{}{"foo@3333", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - libdocker.NewCalledDetail("remove_image", []interface{}{"example.com/foo@3333", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - libdocker.NewCalledDetail("remove_image", []interface{}{"3333", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - }, - }, - "no tags multiple repo digests": { - dockertypes.ImageInspect{ID: "4444", RepoTags: []string{}, RepoDigests: []string{"foo@4444", "example.com/foo@4444"}}, - []libdocker.CalledDetail{ - libdocker.NewCalledDetail("inspect_image", nil), - libdocker.NewCalledDetail("remove_image", []interface{}{"foo@4444", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - libdocker.NewCalledDetail("remove_image", []interface{}{"example.com/foo@4444", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - libdocker.NewCalledDetail("remove_image", []interface{}{"4444", dockertypes.ImageRemoveOptions{PruneChildren: true}}), - }, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - ds, fakeDocker, _ := newTestDockerService() - fakeDocker.InjectImageInspects([]dockertypes.ImageInspect{test.image}) - ds.RemoveImage(getTestCTX(), &runtimeapi.RemoveImageRequest{Image: &runtimeapi.ImageSpec{Image: test.image.ID}}) - err := fakeDocker.AssertCallDetails(test.calledDetails...) - assert.NoError(t, err) - }) - } -} - -func TestPullWithJSONError(t *testing.T) { - ds, fakeDocker, _ := newTestDockerService() - tests := map[string]struct { - image *runtimeapi.ImageSpec - err error - expectedError string - }{ - "Json error": { - &runtimeapi.ImageSpec{Image: "ubuntu"}, - &jsonmessage.JSONError{Code: 50, Message: "Json error"}, - "Json error", - }, - "Bad gateway": { - &runtimeapi.ImageSpec{Image: "ubuntu"}, - &jsonmessage.JSONError{Code: 502, Message: "\n\n \n \n \n

Oops, there was an error!

\n

We have been contacted of this error, feel free to check out status.docker.com\n to see if there is a bigger issue.

\n\n \n"}, - "RegistryUnavailable", - }, - } - for key, test := range tests { - fakeDocker.InjectError("pull", test.err) - _, err := ds.PullImage(getTestCTX(), &runtimeapi.PullImageRequest{Image: test.image, Auth: &runtimeapi.AuthConfig{}}) - require.Error(t, err, fmt.Sprintf("TestCase [%s]", key)) - assert.Contains(t, err.Error(), test.expectedError) - } -} diff --git a/pkg/kubelet/dockershim/docker_image_unsupported.go b/pkg/kubelet/dockershim/docker_image_unsupported.go deleted file mode 100644 index 02420213e54..00000000000 --- a/pkg/kubelet/dockershim/docker_image_unsupported.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build !linux && !windows && !dockerless -// +build !linux,!windows,!dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "fmt" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// ImageFsInfo returns information of the filesystem that is used to store images. -func (ds *dockerService) ImageFsInfo(_ context.Context, r *runtimeapi.ImageFsInfoRequest) (*runtimeapi.ImageFsInfoResponse, error) { - return nil, fmt.Errorf("not implemented") -} diff --git a/pkg/kubelet/dockershim/docker_image_windows.go b/pkg/kubelet/dockershim/docker_image_windows.go deleted file mode 100644 index ad617116677..00000000000 --- a/pkg/kubelet/dockershim/docker_image_windows.go +++ /dev/null @@ -1,52 +0,0 @@ -//go:build windows && !dockerless -// +build windows,!dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "time" - - "k8s.io/klog/v2" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/winstats" -) - -// ImageFsInfo returns information of the filesystem that is used to store images. -func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInfoRequest) (*runtimeapi.ImageFsInfoResponse, error) { - statsClient := &winstats.StatsClient{} - fsinfo, err := statsClient.GetDirFsInfo(ds.dockerRootDir) - if err != nil { - klog.ErrorS(err, "Failed to get fsInfo for dockerRootDir", "path", ds.dockerRootDir) - return nil, err - } - - filesystems := []*runtimeapi.FilesystemUsage{ - { - Timestamp: time.Now().UnixNano(), - UsedBytes: &runtimeapi.UInt64Value{Value: fsinfo.Usage}, - FsId: &runtimeapi.FilesystemIdentifier{ - Mountpoint: ds.dockerRootDir, - }, - }, - } - - return &runtimeapi.ImageFsInfoResponse{ImageFilesystems: filesystems}, nil -} diff --git a/pkg/kubelet/dockershim/docker_legacy_service.go b/pkg/kubelet/dockershim/docker_legacy_service.go deleted file mode 100644 index b2b6529ad9f..00000000000 --- a/pkg/kubelet/dockershim/docker_legacy_service.go +++ /dev/null @@ -1,132 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "errors" - "fmt" - "io" - "strconv" - "time" - - "github.com/armon/circbuf" - dockertypes "github.com/docker/docker/api/types" - - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubetypes "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -// We define `DockerLegacyService` in `pkg/kubelet/legacy`, instead of in this -// file. We make this decision because `pkg/kubelet` depends on -// `DockerLegacyService`, and we want to be able to build the `kubelet` without -// relying on `github.com/docker/docker` or `pkg/kubelet/dockershim`. -// -// See https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/1547-building-kubelet-without-docker/README.md -// for details. - -// GetContainerLogs get container logs directly from docker daemon. -func (d *dockerService) GetContainerLogs(_ context.Context, pod *v1.Pod, containerID kubecontainer.ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) error { - container, err := d.client.InspectContainer(containerID.ID) - if err != nil { - return err - } - - var since int64 - if logOptions.SinceSeconds != nil { - t := metav1.Now().Add(-time.Duration(*logOptions.SinceSeconds) * time.Second) - since = t.Unix() - } - if logOptions.SinceTime != nil { - since = logOptions.SinceTime.Unix() - } - opts := dockertypes.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Since: strconv.FormatInt(since, 10), - Timestamps: logOptions.Timestamps, - Follow: logOptions.Follow, - } - if logOptions.TailLines != nil { - opts.Tail = strconv.FormatInt(*logOptions.TailLines, 10) - } - - if logOptions.LimitBytes != nil { - // stdout and stderr share the total write limit - max := *logOptions.LimitBytes - stderr = sharedLimitWriter(stderr, &max) - stdout = sharedLimitWriter(stdout, &max) - } - sopts := libdocker.StreamOptions{ - OutputStream: stdout, - ErrorStream: stderr, - RawTerminal: container.Config.Tty, - } - err = d.client.Logs(containerID.ID, opts, sopts) - if errors.Is(err, errMaximumWrite) { - klog.V(2).InfoS("Finished logs, hit byte limit", "byteLimit", *logOptions.LimitBytes) - err = nil - } - return err -} - -// GetContainerLogTail attempts to read up to MaxContainerTerminationMessageLogLength -// from the end of the log when docker is configured with a log driver other than json-log. -// It reads up to MaxContainerTerminationMessageLogLines lines. -func (d *dockerService) GetContainerLogTail(uid kubetypes.UID, name, namespace string, containerID kubecontainer.ContainerID) (string, error) { - value := int64(kubecontainer.MaxContainerTerminationMessageLogLines) - buf, _ := circbuf.NewBuffer(kubecontainer.MaxContainerTerminationMessageLogLength) - // Although this is not a full spec pod, dockerLegacyService.GetContainerLogs() currently completely ignores its pod param - pod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - UID: uid, - Name: name, - Namespace: namespace, - }, - } - err := d.GetContainerLogs(context.Background(), pod, containerID, &v1.PodLogOptions{TailLines: &value}, buf, buf) - if err != nil { - return "", err - } - return buf.String(), nil -} - -// criSupportedLogDrivers are log drivers supported by native CRI integration. -var criSupportedLogDrivers = []string{"json-file"} - -// IsCRISupportedLogDriver checks whether the logging driver used by docker is -// supported by native CRI integration. -func (d *dockerService) IsCRISupportedLogDriver() (bool, error) { - info, err := d.client.Info() - if err != nil { - return false, fmt.Errorf("failed to get docker info: %v", err) - } - for _, driver := range criSupportedLogDrivers { - if info.LoggingDriver == driver { - return true, nil - } - } - return false, nil -} diff --git a/pkg/kubelet/dockershim/docker_logs.go b/pkg/kubelet/dockershim/docker_logs.go deleted file mode 100644 index d68903ef15c..00000000000 --- a/pkg/kubelet/dockershim/docker_logs.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "fmt" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// ReopenContainerLog reopens the container log file. -func (ds *dockerService) ReopenContainerLog(_ context.Context, _ *runtimeapi.ReopenContainerLogRequest) (*runtimeapi.ReopenContainerLogResponse, error) { - return nil, fmt.Errorf("docker does not support reopening container log files") -} diff --git a/pkg/kubelet/dockershim/docker_sandbox.go b/pkg/kubelet/dockershim/docker_sandbox.go deleted file mode 100644 index 8914786a91d..00000000000 --- a/pkg/kubelet/dockershim/docker_sandbox.go +++ /dev/null @@ -1,773 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "encoding/json" - "fmt" - "os" - "strings" - "time" - - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - dockerfilters "github.com/docker/docker/api/types/filters" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/klog/v2" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/types" -) - -const ( - defaultSandboxImage = "k8s.gcr.io/pause:3.6" - - // Various default sandbox resources requests/limits. - defaultSandboxCPUshares int64 = 2 - - // defaultSandboxOOMAdj is the oom score adjustment for the docker - // sandbox container. Using this OOM adj makes it very unlikely, but not - // impossible, that the defaultSandox will experience an oom kill. -998 - // is chosen to signify sandbox should be OOM killed before other more - // vital processes like the docker daemon, the kubelet, etc... - defaultSandboxOOMAdj int = -998 - - // Name of the underlying container runtime - runtimeName = "docker" -) - -var ( - // Termination grace period - defaultSandboxGracePeriod = time.Duration(10) * time.Second -) - -// Returns whether the sandbox network is ready, and whether the sandbox is known -func (ds *dockerService) getNetworkReady(podSandboxID string) (bool, bool) { - ds.networkReadyLock.Lock() - defer ds.networkReadyLock.Unlock() - ready, ok := ds.networkReady[podSandboxID] - return ready, ok -} - -func (ds *dockerService) setNetworkReady(podSandboxID string, ready bool) { - ds.networkReadyLock.Lock() - defer ds.networkReadyLock.Unlock() - ds.networkReady[podSandboxID] = ready -} - -func (ds *dockerService) clearNetworkReady(podSandboxID string) { - ds.networkReadyLock.Lock() - defer ds.networkReadyLock.Unlock() - delete(ds.networkReady, podSandboxID) -} - -// RunPodSandbox creates and starts a pod-level sandbox. Runtimes should ensure -// the sandbox is in ready state. -// For docker, PodSandbox is implemented by a container holding the network -// namespace for the pod. -// Note: docker doesn't use LogDirectory (yet). -func (ds *dockerService) RunPodSandbox(ctx context.Context, r *runtimeapi.RunPodSandboxRequest) (*runtimeapi.RunPodSandboxResponse, error) { - config := r.GetConfig() - - // Step 1: Pull the image for the sandbox. - image := defaultSandboxImage - podSandboxImage := ds.podSandboxImage - if len(podSandboxImage) != 0 { - image = podSandboxImage - } - - // NOTE: To use a custom sandbox image in a private repository, users need to configure the nodes with credentials properly. - // see: https://kubernetes.io/docs/user-guide/images/#configuring-nodes-to-authenticate-to-a-private-registry - // Only pull sandbox image when it's not present - v1.PullIfNotPresent. - if err := ensureSandboxImageExists(ds.client, image); err != nil { - return nil, err - } - - // Step 2: Create the sandbox container. - if r.GetRuntimeHandler() != "" && r.GetRuntimeHandler() != runtimeName { - return nil, fmt.Errorf("RuntimeHandler %q not supported", r.GetRuntimeHandler()) - } - createConfig, err := ds.makeSandboxDockerConfig(config, image) - if err != nil { - return nil, fmt.Errorf("failed to make sandbox docker config for pod %q: %v", config.Metadata.Name, err) - } - createResp, err := ds.client.CreateContainer(*createConfig) - if err != nil { - createResp, err = recoverFromCreationConflictIfNeeded(ds.client, *createConfig, err) - } - - if err != nil || createResp == nil { - return nil, fmt.Errorf("failed to create a sandbox for pod %q: %v", config.Metadata.Name, err) - } - resp := &runtimeapi.RunPodSandboxResponse{PodSandboxId: createResp.ID} - - ds.setNetworkReady(createResp.ID, false) - defer func(e *error) { - // Set networking ready depending on the error return of - // the parent function - if *e == nil { - ds.setNetworkReady(createResp.ID, true) - } - }(&err) - - // Step 3: Create Sandbox Checkpoint. - if err = ds.checkpointManager.CreateCheckpoint(createResp.ID, constructPodSandboxCheckpoint(config)); err != nil { - return nil, err - } - - // Step 4: Start the sandbox container. - // Assume kubelet's garbage collector would remove the sandbox later, if - // startContainer failed. - err = ds.client.StartContainer(createResp.ID) - if err != nil { - return nil, fmt.Errorf("failed to start sandbox container for pod %q: %v", config.Metadata.Name, err) - } - - // Rewrite resolv.conf file generated by docker. - // NOTE: cluster dns settings aren't passed anymore to docker api in all cases, - // not only for pods with host network: the resolver conf will be overwritten - // after sandbox creation to override docker's behaviour. This resolv.conf - // file is shared by all containers of the same pod, and needs to be modified - // only once per pod. - if dnsConfig := config.GetDnsConfig(); dnsConfig != nil { - containerInfo, err := ds.client.InspectContainer(createResp.ID) - if err != nil { - return nil, fmt.Errorf("failed to inspect sandbox container for pod %q: %v", config.Metadata.Name, err) - } - - if err := rewriteResolvFile(containerInfo.ResolvConfPath, dnsConfig.Servers, dnsConfig.Searches, dnsConfig.Options); err != nil { - return nil, fmt.Errorf("rewrite resolv.conf failed for pod %q: %v", config.Metadata.Name, err) - } - } - - // Do not invoke network plugins if in hostNetwork mode. - if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtimeapi.NamespaceMode_NODE { - return resp, nil - } - - // Step 5: Setup networking for the sandbox. - // All pod networking is setup by a CNI plugin discovered at startup time. - // This plugin assigns the pod ip, sets up routes inside the sandbox, - // creates interfaces etc. In theory, its jurisdiction ends with pod - // sandbox networking, but it might insert iptables rules or open ports - // on the host as well, to satisfy parts of the pod spec that aren't - // recognized by the CNI standard yet. - cID := kubecontainer.BuildContainerID(runtimeName, createResp.ID) - networkOptions := make(map[string]string) - if dnsConfig := config.GetDnsConfig(); dnsConfig != nil { - // Build DNS options. - dnsOption, err := json.Marshal(dnsConfig) - if err != nil { - return nil, fmt.Errorf("failed to marshal dns config for pod %q: %v", config.Metadata.Name, err) - } - networkOptions["dns"] = string(dnsOption) - } - err = ds.network.SetUpPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID, config.Annotations, networkOptions) - if err != nil { - errList := []error{fmt.Errorf("failed to set up sandbox container %q network for pod %q: %v", createResp.ID, config.Metadata.Name, err)} - - // Ensure network resources are cleaned up even if the plugin - // succeeded but an error happened between that success and here. - err = ds.network.TearDownPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID) - if err != nil { - errList = append(errList, fmt.Errorf("failed to clean up sandbox container %q network for pod %q: %v", createResp.ID, config.Metadata.Name, err)) - } - - err = ds.client.StopContainer(createResp.ID, defaultSandboxGracePeriod) - if err != nil { - errList = append(errList, fmt.Errorf("failed to stop sandbox container %q for pod %q: %v", createResp.ID, config.Metadata.Name, err)) - } - - return resp, utilerrors.NewAggregate(errList) - } - - return resp, nil -} - -// StopPodSandbox stops the sandbox. If there are any running containers in the -// sandbox, they should be force terminated. -// TODO: This function blocks sandbox teardown on networking teardown. Is it -// better to cut our losses assuming an out of band GC routine will cleanup -// after us? -func (ds *dockerService) StopPodSandbox(ctx context.Context, r *runtimeapi.StopPodSandboxRequest) (*runtimeapi.StopPodSandboxResponse, error) { - var namespace, name string - var hostNetwork bool - - podSandboxID := r.PodSandboxId - resp := &runtimeapi.StopPodSandboxResponse{} - - // Try to retrieve minimal sandbox information from docker daemon or sandbox checkpoint. - inspectResult, metadata, statusErr := ds.getPodSandboxDetails(podSandboxID) - if statusErr == nil { - namespace = metadata.Namespace - name = metadata.Name - hostNetwork = (networkNamespaceMode(inspectResult) == runtimeapi.NamespaceMode_NODE) - } else { - checkpoint := NewPodSandboxCheckpoint("", "", &CheckpointData{}) - checkpointErr := ds.checkpointManager.GetCheckpoint(podSandboxID, checkpoint) - - // Proceed if both sandbox container and checkpoint could not be found. This means that following - // actions will only have sandbox ID and not have pod namespace and name information. - // Return error if encounter any unexpected error. - if checkpointErr != nil { - if checkpointErr != errors.ErrCheckpointNotFound { - err := ds.checkpointManager.RemoveCheckpoint(podSandboxID) - if err != nil { - klog.ErrorS(err, "Failed to delete corrupt checkpoint for sandbox", "podSandboxID", podSandboxID) - } - } - if libdocker.IsContainerNotFoundError(statusErr) { - klog.InfoS("Both sandbox container and checkpoint could not be found. Proceed without further sandbox information.", "podSandboxID", podSandboxID) - } else { - return nil, utilerrors.NewAggregate([]error{ - fmt.Errorf("failed to get checkpoint for sandbox %q: %v", podSandboxID, checkpointErr), - fmt.Errorf("failed to get sandbox status: %v", statusErr)}) - } - } else { - _, name, namespace, _, hostNetwork = checkpoint.GetData() - } - } - - // WARNING: The following operations made the following assumption: - // 1. kubelet will retry on any error returned by StopPodSandbox. - // 2. tearing down network and stopping sandbox container can succeed in any sequence. - // This depends on the implementation detail of network plugin and proper error handling. - // For kubenet, if tearing down network failed and sandbox container is stopped, kubelet - // will retry. On retry, kubenet will not be able to retrieve network namespace of the sandbox - // since it is stopped. With empty network namespace, CNI bridge plugin will conduct best - // effort clean up and will not return error. - errList := []error{} - ready, ok := ds.getNetworkReady(podSandboxID) - if !hostNetwork && (ready || !ok) { - // Only tear down the pod network if we haven't done so already - cID := kubecontainer.BuildContainerID(runtimeName, podSandboxID) - err := ds.network.TearDownPod(namespace, name, cID) - if err == nil { - ds.setNetworkReady(podSandboxID, false) - } else { - errList = append(errList, err) - } - } - if err := ds.client.StopContainer(podSandboxID, defaultSandboxGracePeriod); err != nil { - // Do not return error if the container does not exist - if !libdocker.IsContainerNotFoundError(err) { - klog.ErrorS(err, "Failed to stop sandbox", "podSandboxID", podSandboxID) - errList = append(errList, err) - } else { - // remove the checkpoint for any sandbox that is not found in the runtime - ds.checkpointManager.RemoveCheckpoint(podSandboxID) - } - } - - if len(errList) == 0 { - return resp, nil - } - - // TODO: Stop all running containers in the sandbox. - return nil, utilerrors.NewAggregate(errList) -} - -// RemovePodSandbox removes the sandbox. If there are running containers in the -// sandbox, they should be forcibly removed. -func (ds *dockerService) RemovePodSandbox(ctx context.Context, r *runtimeapi.RemovePodSandboxRequest) (*runtimeapi.RemovePodSandboxResponse, error) { - podSandboxID := r.PodSandboxId - var errs []error - - opts := dockertypes.ContainerListOptions{All: true} - - opts.Filters = dockerfilters.NewArgs() - f := newDockerFilter(&opts.Filters) - f.AddLabel(sandboxIDLabelKey, podSandboxID) - - containers, err := ds.client.ListContainers(opts) - if err != nil { - errs = append(errs, err) - } - - // Remove all containers in the sandbox. - for i := range containers { - if _, err := ds.RemoveContainer(ctx, &runtimeapi.RemoveContainerRequest{ContainerId: containers[i].ID}); err != nil && !libdocker.IsContainerNotFoundError(err) { - errs = append(errs, err) - } - } - - // Remove the sandbox container. - err = ds.client.RemoveContainer(podSandboxID, dockertypes.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) - if err == nil || libdocker.IsContainerNotFoundError(err) { - // Only clear network ready when the sandbox has actually been - // removed from docker or doesn't exist - ds.clearNetworkReady(podSandboxID) - } else { - errs = append(errs, err) - } - - // Remove the checkpoint of the sandbox. - if err := ds.checkpointManager.RemoveCheckpoint(podSandboxID); err != nil { - errs = append(errs, err) - } - if len(errs) == 0 { - return &runtimeapi.RemovePodSandboxResponse{}, nil - } - return nil, utilerrors.NewAggregate(errs) -} - -// getIPsFromPlugin interrogates the network plugin for sandbox IPs. -func (ds *dockerService) getIPsFromPlugin(sandbox *dockertypes.ContainerJSON) ([]string, error) { - metadata, err := parseSandboxName(sandbox.Name) - if err != nil { - return nil, err - } - msg := fmt.Sprintf("Couldn't find network status for %s/%s through plugin", metadata.Namespace, metadata.Name) - cID := kubecontainer.BuildContainerID(runtimeName, sandbox.ID) - networkStatus, err := ds.network.GetPodNetworkStatus(metadata.Namespace, metadata.Name, cID) - if err != nil { - return nil, err - } - if networkStatus == nil { - return nil, fmt.Errorf("%v: invalid network status for", msg) - } - - ips := make([]string, 0) - for _, ip := range networkStatus.IPs { - ips = append(ips, ip.String()) - } - // if we don't have any ip in our list then cni is using classic primary IP only - if len(ips) == 0 { - ips = append(ips, networkStatus.IP.String()) - } - return ips, nil -} - -// getIPs returns the ip given the output of `docker inspect` on a pod sandbox, -// first interrogating any registered plugins, then simply trusting the ip -// in the sandbox itself. We look for an ipv4 address before ipv6. -func (ds *dockerService) getIPs(podSandboxID string, sandbox *dockertypes.ContainerJSON) []string { - if sandbox.NetworkSettings == nil { - return nil - } - if networkNamespaceMode(sandbox) == runtimeapi.NamespaceMode_NODE { - // For sandboxes using host network, the shim is not responsible for - // reporting the IP. - return nil - } - - // Don't bother getting IP if the pod is known and networking isn't ready - ready, ok := ds.getNetworkReady(podSandboxID) - if ok && !ready { - return nil - } - - ips, err := ds.getIPsFromPlugin(sandbox) - if err == nil { - return ips - } - - ips = make([]string, 0) - // TODO: trusting the docker ip is not a great idea. However docker uses - // eth0 by default and so does CNI, so if we find a docker IP here, we - // conclude that the plugin must have failed setup, or forgotten its ip. - // This is not a sensible assumption for plugins across the board, but if - // a plugin doesn't want this behavior, it can throw an error. - if sandbox.NetworkSettings.IPAddress != "" { - ips = append(ips, sandbox.NetworkSettings.IPAddress) - } - if sandbox.NetworkSettings.GlobalIPv6Address != "" { - ips = append(ips, sandbox.NetworkSettings.GlobalIPv6Address) - } - - // If all else fails, warn but don't return an error, as pod status - // should generally not return anything except fatal errors - // FIXME: handle network errors by restarting the pod somehow? - klog.InfoS("Failed to read pod IP from plugin/docker", "err", err) - return ips -} - -// Returns the inspect container response, the sandbox metadata, and network namespace mode -func (ds *dockerService) getPodSandboxDetails(podSandboxID string) (*dockertypes.ContainerJSON, *runtimeapi.PodSandboxMetadata, error) { - resp, err := ds.client.InspectContainer(podSandboxID) - if err != nil { - return nil, nil, err - } - - metadata, err := parseSandboxName(resp.Name) - if err != nil { - return nil, nil, err - } - - return resp, metadata, nil -} - -// PodSandboxStatus returns the status of the PodSandbox. -func (ds *dockerService) PodSandboxStatus(ctx context.Context, req *runtimeapi.PodSandboxStatusRequest) (*runtimeapi.PodSandboxStatusResponse, error) { - podSandboxID := req.PodSandboxId - - r, metadata, err := ds.getPodSandboxDetails(podSandboxID) - if err != nil { - return nil, err - } - - // Parse the timestamps. - createdAt, _, _, err := getContainerTimestamps(r) - if err != nil { - return nil, fmt.Errorf("failed to parse timestamp for container %q: %v", podSandboxID, err) - } - ct := createdAt.UnixNano() - - // Translate container to sandbox state. - state := runtimeapi.PodSandboxState_SANDBOX_NOTREADY - if r.State.Running { - state = runtimeapi.PodSandboxState_SANDBOX_READY - } - - var ips []string - // TODO: Remove this when sandbox is available on windows - // This is a workaround for windows, where sandbox is not in use, and pod IP is determined through containers belonging to the Pod. - if ips = ds.determinePodIPBySandboxID(podSandboxID); len(ips) == 0 { - ips = ds.getIPs(podSandboxID, r) - } - - // ip is primary ips - // ips is all other ips - ip := "" - if len(ips) != 0 { - ip = ips[0] - ips = ips[1:] - } - - labels, annotations := extractLabels(r.Config.Labels) - status := &runtimeapi.PodSandboxStatus{ - Id: r.ID, - State: state, - CreatedAt: ct, - Metadata: metadata, - Labels: labels, - Annotations: annotations, - Network: &runtimeapi.PodSandboxNetworkStatus{ - Ip: ip, - }, - Linux: &runtimeapi.LinuxPodSandboxStatus{ - Namespaces: &runtimeapi.Namespace{ - Options: &runtimeapi.NamespaceOption{ - Network: networkNamespaceMode(r), - Pid: pidNamespaceMode(r), - Ipc: ipcNamespaceMode(r), - }, - }, - }, - } - // add additional IPs - additionalPodIPs := make([]*runtimeapi.PodIP, 0, len(ips)) - for _, ip := range ips { - additionalPodIPs = append(additionalPodIPs, &runtimeapi.PodIP{ - Ip: ip, - }) - } - status.Network.AdditionalIps = additionalPodIPs - return &runtimeapi.PodSandboxStatusResponse{Status: status}, nil -} - -// ListPodSandbox returns a list of Sandbox. -func (ds *dockerService) ListPodSandbox(_ context.Context, r *runtimeapi.ListPodSandboxRequest) (*runtimeapi.ListPodSandboxResponse, error) { - filter := r.GetFilter() - - // By default, list all containers whether they are running or not. - opts := dockertypes.ContainerListOptions{All: true} - filterOutReadySandboxes := false - - opts.Filters = dockerfilters.NewArgs() - f := newDockerFilter(&opts.Filters) - // Add filter to select only sandbox containers. - f.AddLabel(containerTypeLabelKey, containerTypeLabelSandbox) - - if filter != nil { - if filter.Id != "" { - f.Add("id", filter.Id) - } - if filter.State != nil { - if filter.GetState().State == runtimeapi.PodSandboxState_SANDBOX_READY { - // Only list running containers. - opts.All = false - } else { - // runtimeapi.PodSandboxState_SANDBOX_NOTREADY can mean the - // container is in any of the non-running state (e.g., created, - // exited). We can't tell docker to filter out running - // containers directly, so we'll need to filter them out - // ourselves after getting the results. - filterOutReadySandboxes = true - } - } - - if filter.LabelSelector != nil { - for k, v := range filter.LabelSelector { - f.AddLabel(k, v) - } - } - } - - // Make sure we get the list of checkpoints first so that we don't include - // new PodSandboxes that are being created right now. - var err error - checkpoints := []string{} - if filter == nil { - checkpoints, err = ds.checkpointManager.ListCheckpoints() - if err != nil { - klog.ErrorS(err, "Failed to list checkpoints") - } - } - - containers, err := ds.client.ListContainers(opts) - if err != nil { - return nil, err - } - - // Convert docker containers to runtime api sandboxes. - result := []*runtimeapi.PodSandbox{} - // using map as set - sandboxIDs := make(map[string]bool) - for i := range containers { - c := containers[i] - converted, err := containerToRuntimeAPISandbox(&c) - if err != nil { - klog.V(4).InfoS("Unable to convert docker to runtime API sandbox", "containerName", c.Names, "err", err) - continue - } - if filterOutReadySandboxes && converted.State == runtimeapi.PodSandboxState_SANDBOX_READY { - continue - } - sandboxIDs[converted.Id] = true - result = append(result, converted) - } - - // Include sandbox that could only be found with its checkpoint if no filter is applied - // These PodSandbox will only include PodSandboxID, Name, Namespace. - // These PodSandbox will be in PodSandboxState_SANDBOX_NOTREADY state. - for _, id := range checkpoints { - if _, ok := sandboxIDs[id]; ok { - continue - } - checkpoint := NewPodSandboxCheckpoint("", "", &CheckpointData{}) - err := ds.checkpointManager.GetCheckpoint(id, checkpoint) - if err != nil { - klog.ErrorS(err, "Failed to retrieve checkpoint for sandbox", "sandboxID", id) - if err == errors.ErrCorruptCheckpoint { - err = ds.checkpointManager.RemoveCheckpoint(id) - if err != nil { - klog.ErrorS(err, "Failed to delete corrupt checkpoint for sandbox", "sandboxID", id) - } - } - continue - } - result = append(result, checkpointToRuntimeAPISandbox(id, checkpoint)) - } - - return &runtimeapi.ListPodSandboxResponse{Items: result}, nil -} - -// applySandboxLinuxOptions applies LinuxPodSandboxConfig to dockercontainer.HostConfig and dockercontainer.ContainerCreateConfig. -func (ds *dockerService) applySandboxLinuxOptions(hc *dockercontainer.HostConfig, lc *runtimeapi.LinuxPodSandboxConfig, createConfig *dockertypes.ContainerCreateConfig, image string, separator rune) error { - if lc == nil { - return nil - } - // Apply security context. - if err := applySandboxSecurityContext(lc, createConfig.Config, hc, ds.network, separator); err != nil { - return err - } - - // Set sysctls. - hc.Sysctls = lc.Sysctls - return nil -} - -func (ds *dockerService) applySandboxResources(hc *dockercontainer.HostConfig, lc *runtimeapi.LinuxPodSandboxConfig) error { - hc.Resources = dockercontainer.Resources{ - MemorySwap: DefaultMemorySwap(), - CPUShares: defaultSandboxCPUshares, - // Use docker's default cpu quota/period. - } - - if lc != nil { - // Apply Cgroup options. - cgroupParent, err := ds.GenerateExpectedCgroupParent(lc.CgroupParent) - if err != nil { - return err - } - hc.CgroupParent = cgroupParent - } - return nil -} - -// makeSandboxDockerConfig returns dockertypes.ContainerCreateConfig based on runtimeapi.PodSandboxConfig. -func (ds *dockerService) makeSandboxDockerConfig(c *runtimeapi.PodSandboxConfig, image string) (*dockertypes.ContainerCreateConfig, error) { - // Merge annotations and labels because docker supports only labels. - labels := makeLabels(c.GetLabels(), c.GetAnnotations()) - // Apply a label to distinguish sandboxes from regular containers. - labels[containerTypeLabelKey] = containerTypeLabelSandbox - // Apply a container name label for infra container. This is used in summary v1. - // TODO(random-liu): Deprecate this label once container metrics is directly got from CRI. - labels[types.KubernetesContainerNameLabel] = sandboxContainerName - - hc := &dockercontainer.HostConfig{ - IpcMode: dockercontainer.IpcMode("shareable"), - } - createConfig := &dockertypes.ContainerCreateConfig{ - Name: makeSandboxName(c), - Config: &dockercontainer.Config{ - Hostname: c.Hostname, - // TODO: Handle environment variables. - Image: image, - Labels: labels, - }, - HostConfig: hc, - } - - // Apply linux-specific options. - if err := ds.applySandboxLinuxOptions(hc, c.GetLinux(), createConfig, image, securityOptSeparator); err != nil { - return nil, err - } - - // Set port mappings. - exposedPorts, portBindings := makePortsAndBindings(c.GetPortMappings()) - createConfig.Config.ExposedPorts = exposedPorts - hc.PortBindings = portBindings - - hc.OomScoreAdj = defaultSandboxOOMAdj - - // Apply resource options. - if err := ds.applySandboxResources(hc, c.GetLinux()); err != nil { - return nil, err - } - - // Set security options. - securityOpts := ds.getSandBoxSecurityOpts(securityOptSeparator) - hc.SecurityOpt = append(hc.SecurityOpt, securityOpts...) - - return createConfig, nil -} - -// networkNamespaceMode returns the network runtimeapi.NamespaceMode for this container. -// Supports: POD, NODE -func networkNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.NamespaceMode { - if container != nil && container.HostConfig != nil && string(container.HostConfig.NetworkMode) == namespaceModeHost { - return runtimeapi.NamespaceMode_NODE - } - return runtimeapi.NamespaceMode_POD -} - -// pidNamespaceMode returns the PID runtimeapi.NamespaceMode for this container. -// Supports: CONTAINER, NODE -// TODO(verb): add support for POD PID namespace sharing -func pidNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.NamespaceMode { - if container != nil && container.HostConfig != nil && string(container.HostConfig.PidMode) == namespaceModeHost { - return runtimeapi.NamespaceMode_NODE - } - return runtimeapi.NamespaceMode_CONTAINER -} - -// ipcNamespaceMode returns the IPC runtimeapi.NamespaceMode for this container. -// Supports: POD, NODE -func ipcNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.NamespaceMode { - if container != nil && container.HostConfig != nil && string(container.HostConfig.IpcMode) == namespaceModeHost { - return runtimeapi.NamespaceMode_NODE - } - return runtimeapi.NamespaceMode_POD -} - -func constructPodSandboxCheckpoint(config *runtimeapi.PodSandboxConfig) checkpointmanager.Checkpoint { - data := CheckpointData{} - for _, pm := range config.GetPortMappings() { - proto := toCheckpointProtocol(pm.Protocol) - data.PortMappings = append(data.PortMappings, &PortMapping{ - HostPort: &pm.HostPort, - ContainerPort: &pm.ContainerPort, - Protocol: &proto, - HostIP: pm.HostIp, - }) - } - if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtimeapi.NamespaceMode_NODE { - data.HostNetwork = true - } - return NewPodSandboxCheckpoint(config.Metadata.Namespace, config.Metadata.Name, &data) -} - -func toCheckpointProtocol(protocol runtimeapi.Protocol) Protocol { - switch protocol { - case runtimeapi.Protocol_TCP: - return protocolTCP - case runtimeapi.Protocol_UDP: - return protocolUDP - case runtimeapi.Protocol_SCTP: - return protocolSCTP - } - klog.InfoS("Unknown protocol, defaulting to TCP", "protocol", protocol) - return protocolTCP -} - -// rewriteResolvFile rewrites resolv.conf file generated by docker. -func rewriteResolvFile(resolvFilePath string, dns []string, dnsSearch []string, dnsOptions []string) error { - if len(resolvFilePath) == 0 { - klog.ErrorS(nil, "ResolvConfPath is empty.") - return nil - } - - if _, err := os.Stat(resolvFilePath); os.IsNotExist(err) { - return fmt.Errorf("ResolvConfPath %q does not exist", resolvFilePath) - } - - var resolvFileContent []string - for _, srv := range dns { - resolvFileContent = append(resolvFileContent, "nameserver "+srv) - } - - if len(dnsSearch) > 0 { - resolvFileContent = append(resolvFileContent, "search "+strings.Join(dnsSearch, " ")) - } - - if len(dnsOptions) > 0 { - resolvFileContent = append(resolvFileContent, "options "+strings.Join(dnsOptions, " ")) - } - - if len(resolvFileContent) > 0 { - resolvFileContentStr := strings.Join(resolvFileContent, "\n") - resolvFileContentStr += "\n" - - klog.V(4).InfoS("Will attempt to re-write config file", "path", resolvFilePath, "fileContent", resolvFileContent) - if err := rewriteFile(resolvFilePath, resolvFileContentStr); err != nil { - klog.ErrorS(err, "Resolv.conf could not be updated") - return err - } - } - - return nil -} - -func rewriteFile(filePath, stringToWrite string) error { - f, err := os.OpenFile(filePath, os.O_TRUNC|os.O_WRONLY, 0644) - if err != nil { - return err - } - defer f.Close() - - _, err = f.WriteString(stringToWrite) - return err -} diff --git a/pkg/kubelet/dockershim/docker_sandbox_linux_test.go b/pkg/kubelet/dockershim/docker_sandbox_linux_test.go deleted file mode 100644 index 2c6acfbf440..00000000000 --- a/pkg/kubelet/dockershim/docker_sandbox_linux_test.go +++ /dev/null @@ -1,39 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -// TestSandboxHasLeastPrivilegesConfig tests that the sandbox is set with no-new-privileges -// and it uses runtime/default seccomp profile. -func TestSandboxHasLeastPrivilegesConfig(t *testing.T) { - ds, _, _ := newTestDockerService() - config := makeSandboxConfig("foo", "bar", "1", 0) - - // test the default - createConfig, err := ds.makeSandboxDockerConfig(config, defaultSandboxImage) - assert.NoError(t, err) - assert.Equal(t, len(createConfig.HostConfig.SecurityOpt), 1, "sandbox should use runtime/default") - assert.Equal(t, "no-new-privileges", createConfig.HostConfig.SecurityOpt[0], "no-new-privileges not set") -} diff --git a/pkg/kubelet/dockershim/docker_sandbox_test.go b/pkg/kubelet/dockershim/docker_sandbox_test.go deleted file mode 100644 index c2c2e2c6100..00000000000 --- a/pkg/kubelet/dockershim/docker_sandbox_test.go +++ /dev/null @@ -1,314 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "errors" - "fmt" - "math/rand" - "net" - "testing" - "time" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - nettest "k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing" - "k8s.io/kubernetes/pkg/kubelet/types" -) - -// A helper to create a basic config. -func makeSandboxConfig(name, namespace, uid string, attempt uint32) *runtimeapi.PodSandboxConfig { - return makeSandboxConfigWithLabelsAndAnnotations(name, namespace, uid, attempt, map[string]string{}, map[string]string{}) -} - -func makeSandboxConfigWithLabelsAndAnnotations(name, namespace, uid string, attempt uint32, labels, annotations map[string]string) *runtimeapi.PodSandboxConfig { - return &runtimeapi.PodSandboxConfig{ - Metadata: &runtimeapi.PodSandboxMetadata{ - Name: name, - Namespace: namespace, - Uid: uid, - Attempt: attempt, - }, - Labels: labels, - Annotations: annotations, - } -} - -// TestListSandboxes creates several sandboxes and then list them to check -// whether the correct metadatas, states, and labels are returned. -func TestListSandboxes(t *testing.T) { - ds, _, fakeClock := newTestDockerService() - name, namespace := "foo", "bar" - configs := []*runtimeapi.PodSandboxConfig{} - for i := 0; i < 3; i++ { - c := makeSandboxConfigWithLabelsAndAnnotations(fmt.Sprintf("%s%d", name, i), - fmt.Sprintf("%s%d", namespace, i), fmt.Sprintf("%d", i), 0, - map[string]string{"label": fmt.Sprintf("foo%d", i)}, - map[string]string{"annotation": fmt.Sprintf("bar%d", i)}, - ) - configs = append(configs, c) - } - - expected := []*runtimeapi.PodSandbox{} - state := runtimeapi.PodSandboxState_SANDBOX_READY - var createdAt int64 = fakeClock.Now().UnixNano() - for i := range configs { - runResp, err := ds.RunPodSandbox(getTestCTX(), &runtimeapi.RunPodSandboxRequest{Config: configs[i]}) - require.NoError(t, err) - // Prepend to the expected list because ListPodSandbox returns - // the most recent sandbox first. - expected = append([]*runtimeapi.PodSandbox{{ - Metadata: configs[i].Metadata, - Id: runResp.PodSandboxId, - State: state, - CreatedAt: createdAt, - Labels: configs[i].Labels, - Annotations: configs[i].Annotations, - }}, expected...) - } - listResp, err := ds.ListPodSandbox(getTestCTX(), &runtimeapi.ListPodSandboxRequest{}) - require.NoError(t, err) - assert.Len(t, listResp.Items, len(expected)) - assert.Equal(t, expected, listResp.Items) -} - -// TestSandboxStatus tests the basic lifecycle operations and verify that -// the status returned reflects the operations performed. -func TestSandboxStatus(t *testing.T) { - ds, fDocker, fClock := newTestDockerService() - labels := map[string]string{"label": "foobar1"} - annotations := map[string]string{"annotation": "abc"} - config := makeSandboxConfigWithLabelsAndAnnotations("foo", "bar", "1", 0, labels, annotations) - r := rand.New(rand.NewSource(0)).Uint32() - podIP := fmt.Sprintf("10.%d.%d.%d", byte(r>>16), byte(r>>8), byte(r)) - - state := runtimeapi.PodSandboxState_SANDBOX_READY - ct := int64(0) - expected := &runtimeapi.PodSandboxStatus{ - State: state, - CreatedAt: ct, - Metadata: config.Metadata, - Network: &runtimeapi.PodSandboxNetworkStatus{Ip: podIP, AdditionalIps: []*runtimeapi.PodIP{}}, - Linux: &runtimeapi.LinuxPodSandboxStatus{ - Namespaces: &runtimeapi.Namespace{ - Options: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_CONTAINER, - }, - }, - }, - Labels: labels, - Annotations: annotations, - } - - // Create the sandbox. - fClock.SetTime(time.Now()) - expected.CreatedAt = fClock.Now().UnixNano() - runResp, err := ds.RunPodSandbox(getTestCTX(), &runtimeapi.RunPodSandboxRequest{Config: config}) - require.NoError(t, err) - id := runResp.PodSandboxId - - // Check internal labels - c, err := fDocker.InspectContainer(id) - assert.NoError(t, err) - assert.Equal(t, c.Config.Labels[containerTypeLabelKey], containerTypeLabelSandbox) - assert.Equal(t, c.Config.Labels[types.KubernetesContainerNameLabel], sandboxContainerName) - - expected.Id = id // ID is only known after the creation. - statusResp, err := ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) - require.NoError(t, err) - assert.Equal(t, expected, statusResp.Status) - - // Stop the sandbox. - expected.State = runtimeapi.PodSandboxState_SANDBOX_NOTREADY - _, err = ds.StopPodSandbox(getTestCTX(), &runtimeapi.StopPodSandboxRequest{PodSandboxId: id}) - require.NoError(t, err) - // IP not valid after sandbox stop - expected.Network.Ip = "" - expected.Network.AdditionalIps = []*runtimeapi.PodIP{} - statusResp, err = ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) - require.NoError(t, err) - assert.Equal(t, expected, statusResp.Status) - - // Remove the container. - _, err = ds.RemovePodSandbox(getTestCTX(), &runtimeapi.RemovePodSandboxRequest{PodSandboxId: id}) - require.NoError(t, err) - statusResp, err = ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) - assert.Error(t, err, fmt.Sprintf("status of sandbox: %+v", statusResp)) -} - -// TestSandboxStatusAfterRestart tests that retrieving sandbox status returns -// an IP address even if RunPodSandbox() was not yet called for this pod, as -// would happen on kubelet restart -func TestSandboxStatusAfterRestart(t *testing.T) { - ds, _, fClock := newTestDockerService() - config := makeSandboxConfig("foo", "bar", "1", 0) - r := rand.New(rand.NewSource(0)).Uint32() - podIP := fmt.Sprintf("10.%d.%d.%d", byte(r>>16), byte(r>>8), byte(r)) - state := runtimeapi.PodSandboxState_SANDBOX_READY - ct := int64(0) - expected := &runtimeapi.PodSandboxStatus{ - State: state, - CreatedAt: ct, - Metadata: config.Metadata, - Network: &runtimeapi.PodSandboxNetworkStatus{Ip: podIP, AdditionalIps: []*runtimeapi.PodIP{}}, - Linux: &runtimeapi.LinuxPodSandboxStatus{ - Namespaces: &runtimeapi.Namespace{ - Options: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_CONTAINER, - }, - }, - }, - Labels: map[string]string{}, - Annotations: map[string]string{}, - } - - // Create the sandbox. - fClock.SetTime(time.Now()) - expected.CreatedAt = fClock.Now().UnixNano() - - createConfig, err := ds.makeSandboxDockerConfig(config, defaultSandboxImage) - assert.NoError(t, err) - - createResp, err := ds.client.CreateContainer(*createConfig) - assert.NoError(t, err) - err = ds.client.StartContainer(createResp.ID) - assert.NoError(t, err) - - // Check status without RunPodSandbox() having set up networking - expected.Id = createResp.ID // ID is only known after the creation. - - statusResp, err := ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: createResp.ID}) - require.NoError(t, err) - assert.Equal(t, expected, statusResp.Status) -} - -// TestNetworkPluginInvocation checks that the right SetUpPod and TearDownPod -// calls are made when we run/stop a sandbox. -func TestNetworkPluginInvocation(t *testing.T) { - ds, _, _ := newTestDockerService() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockPlugin := nettest.NewMockNetworkPlugin(ctrl) - ds.network = network.NewPluginManager(mockPlugin) - - name := "foo0" - ns := "bar0" - c := makeSandboxConfigWithLabelsAndAnnotations( - name, ns, "0", 0, - map[string]string{"label": name}, - map[string]string{"annotation": ns}, - ) - cID := kubecontainer.ContainerID{Type: runtimeName, ID: libdocker.GetFakeContainerID(fmt.Sprintf("/%v", makeSandboxName(c)))} - - mockPlugin.EXPECT().Name().Return("mockNetworkPlugin").AnyTimes() - setup := mockPlugin.EXPECT().SetUpPod(ns, name, cID, map[string]string{"annotation": ns}, map[string]string{}) - mockPlugin.EXPECT().TearDownPod(ns, name, cID).After(setup) - - _, err := ds.RunPodSandbox(getTestCTX(), &runtimeapi.RunPodSandboxRequest{Config: c}) - require.NoError(t, err) - _, err = ds.StopPodSandbox(getTestCTX(), &runtimeapi.StopPodSandboxRequest{PodSandboxId: cID.ID}) - require.NoError(t, err) -} - -// TestHostNetworkPluginInvocation checks that *no* SetUp/TearDown calls happen -// for host network sandboxes. -func TestHostNetworkPluginInvocation(t *testing.T) { - ds, _, _ := newTestDockerService() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockPlugin := nettest.NewMockNetworkPlugin(ctrl) - ds.network = network.NewPluginManager(mockPlugin) - - name := "foo0" - ns := "bar0" - c := makeSandboxConfigWithLabelsAndAnnotations( - name, ns, "0", 0, - map[string]string{"label": name}, - map[string]string{"annotation": ns}, - ) - c.Linux = &runtimeapi.LinuxPodSandboxConfig{ - SecurityContext: &runtimeapi.LinuxSandboxSecurityContext{ - NamespaceOptions: &runtimeapi.NamespaceOption{ - Network: runtimeapi.NamespaceMode_NODE, - }, - }, - } - cID := kubecontainer.ContainerID{Type: runtimeName, ID: libdocker.GetFakeContainerID(fmt.Sprintf("/%v", makeSandboxName(c)))} - - // No calls to network plugin are expected - _, err := ds.RunPodSandbox(getTestCTX(), &runtimeapi.RunPodSandboxRequest{Config: c}) - require.NoError(t, err) - - _, err = ds.StopPodSandbox(getTestCTX(), &runtimeapi.StopPodSandboxRequest{PodSandboxId: cID.ID}) - require.NoError(t, err) -} - -// TestSetUpPodFailure checks that the sandbox should be not ready when it -// hits a SetUpPod failure. -func TestSetUpPodFailure(t *testing.T) { - ds, _, _ := newTestDockerService() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockPlugin := nettest.NewMockNetworkPlugin(ctrl) - ds.network = network.NewPluginManager(mockPlugin) - - name := "foo0" - ns := "bar0" - c := makeSandboxConfigWithLabelsAndAnnotations( - name, ns, "0", 0, - map[string]string{"label": name}, - map[string]string{"annotation": ns}, - ) - cID := kubecontainer.ContainerID{Type: runtimeName, ID: libdocker.GetFakeContainerID(fmt.Sprintf("/%v", makeSandboxName(c)))} - mockPlugin.EXPECT().Name().Return("mockNetworkPlugin").AnyTimes() - mockPlugin.EXPECT().SetUpPod(ns, name, cID, map[string]string{"annotation": ns}, map[string]string{}).Return(errors.New("setup pod error")).AnyTimes() - // If SetUpPod() fails, we expect TearDownPod() to immediately follow - mockPlugin.EXPECT().TearDownPod(ns, name, cID) - // Assume network plugin doesn't return error, dockershim should still be able to return not ready correctly. - mockPlugin.EXPECT().GetPodNetworkStatus(ns, name, cID).Return(&network.PodNetworkStatus{IP: net.IP("127.0.0.01")}, nil).AnyTimes() - - t.Logf("RunPodSandbox should return error") - _, err := ds.RunPodSandbox(getTestCTX(), &runtimeapi.RunPodSandboxRequest{Config: c}) - assert.Error(t, err) - - t.Logf("PodSandboxStatus should be not ready") - statusResp, err := ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: cID.ID}) - require.NoError(t, err) - assert.Equal(t, runtimeapi.PodSandboxState_SANDBOX_NOTREADY, statusResp.Status.State) - - t.Logf("ListPodSandbox should also show not ready") - listResp, err := ds.ListPodSandbox(getTestCTX(), &runtimeapi.ListPodSandboxRequest{}) - require.NoError(t, err) - var sandbox *runtimeapi.PodSandbox - for _, s := range listResp.Items { - if s.Id == cID.ID { - sandbox = s - break - } - } - assert.NotNil(t, sandbox) - assert.Equal(t, runtimeapi.PodSandboxState_SANDBOX_NOTREADY, sandbox.State) -} diff --git a/pkg/kubelet/dockershim/docker_service.go b/pkg/kubelet/dockershim/docker_service.go deleted file mode 100644 index c6ad4aed011..00000000000 --- a/pkg/kubelet/dockershim/docker_service.go +++ /dev/null @@ -1,579 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "fmt" - "net/http" - "os" - "path" - "path/filepath" - "runtime" - "sync" - "time" - - "github.com/blang/semver" - dockertypes "github.com/docker/docker/api/types" - "k8s.io/klog/v2" - - v1 "k8s.io/api/core/v1" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/cri/streaming" - "k8s.io/kubernetes/pkg/kubelet/dockershim/cm" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet" - "k8s.io/kubernetes/pkg/kubelet/legacy" - "k8s.io/kubernetes/pkg/kubelet/util/cache" - - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/dockershim/metrics" -) - -const ( - dockerRuntimeName = "docker" - kubeAPIVersion = "0.1.0" - - // String used to detect docker host mode for various namespaces (e.g. - // networking). Must match the value returned by docker inspect -f - // '{{.HostConfig.NetworkMode}}'. - namespaceModeHost = "host" - - dockerNetNSFmt = "/proc/%v/ns/net" - - // Internal docker labels used to identify whether a container is a sandbox - // or a regular container. - // TODO: This is not backward compatible with older containers. We will - // need to add filtering based on names. - containerTypeLabelKey = "io.kubernetes.docker.type" - containerTypeLabelSandbox = "podsandbox" - containerTypeLabelContainer = "container" - containerLogPathLabelKey = "io.kubernetes.container.logpath" - sandboxIDLabelKey = "io.kubernetes.sandbox.id" - - // The expiration time of version cache. - versionCacheTTL = 60 * time.Second - - defaultCgroupDriver = "cgroupfs" - - // TODO: https://github.com/kubernetes/kubernetes/pull/31169 provides experimental - // defaulting of host user namespace that may be enabled when the docker daemon - // is using remapped UIDs. - // Dockershim should provide detection support for a remapping environment . - // This should be included in the feature proposal. Defaulting may still occur according - // to kubelet behavior and system settings in addition to any API flags that may be introduced. -) - -// CRIService includes all methods necessary for a CRI server. -type CRIService interface { - runtimeapi.RuntimeServiceServer - runtimeapi.ImageServiceServer - Start() error -} - -// DockerService is an interface that embeds the new RuntimeService and -// ImageService interfaces. -type DockerService interface { - CRIService - - // For serving streaming calls. - http.Handler - - // For supporting legacy features. - legacy.DockerLegacyService -} - -// NetworkPluginSettings is the subset of kubelet runtime args we pass -// to the container runtime shim so it can probe for network plugins. -// In the future we will feed these directly to a standalone container -// runtime process. -type NetworkPluginSettings struct { - // HairpinMode is best described by comments surrounding the kubelet arg - HairpinMode kubeletconfig.HairpinMode - // NonMasqueradeCIDR is the range of ips which should *not* be included - // in any MASQUERADE rules applied by the plugin - NonMasqueradeCIDR string - // PluginName is the name of the plugin, runtime shim probes for - PluginName string - // PluginBinDirString is a list of directiores delimited by commas, in - // which the binaries for the plugin with PluginName may be found. - PluginBinDirString string - // PluginBinDirs is an array of directories in which the binaries for - // the plugin with PluginName may be found. The admin is responsible for - // provisioning these binaries before-hand. - PluginBinDirs []string - // PluginConfDir is the directory in which the admin places a CNI conf. - // Depending on the plugin, this may be an optional field, eg: kubenet - // generates its own plugin conf. - PluginConfDir string - // PluginCacheDir is the directory in which CNI should store cache files. - PluginCacheDir string - // MTU is the desired MTU for network devices created by the plugin. - MTU int -} - -// namespaceGetter is a wrapper around the dockerService that implements -// the network.NamespaceGetter interface. -type namespaceGetter struct { - ds *dockerService -} - -func (n *namespaceGetter) GetNetNS(containerID string) (string, error) { - return n.ds.GetNetNS(containerID) -} - -// portMappingGetter is a wrapper around the dockerService that implements -// the network.PortMappingGetter interface. -type portMappingGetter struct { - ds *dockerService -} - -func (p *portMappingGetter) GetPodPortMappings(containerID string) ([]*hostport.PortMapping, error) { - return p.ds.GetPodPortMappings(containerID) -} - -// dockerNetworkHost implements network.Host by wrapping the legacy host passed in by the kubelet -// and dockerServices which implements the rest of the network host interfaces. -// The legacy host methods are slated for deletion. -type dockerNetworkHost struct { - *namespaceGetter - *portMappingGetter -} - -var internalLabelKeys = []string{containerTypeLabelKey, containerLogPathLabelKey, sandboxIDLabelKey} - -// ClientConfig is parameters used to initialize docker client -type ClientConfig struct { - DockerEndpoint string - RuntimeRequestTimeout time.Duration - ImagePullProgressDeadline time.Duration - - // Configuration for fake docker client - EnableSleep bool - WithTraceDisabled bool -} - -// NewDockerClientFromConfig create a docker client from given configure -// return nil if nil configure is given. -func NewDockerClientFromConfig(config *ClientConfig) libdocker.Interface { - if config != nil { - // Create docker client. - client := libdocker.ConnectToDockerOrDie( - config.DockerEndpoint, - config.RuntimeRequestTimeout, - config.ImagePullProgressDeadline, - ) - return client - } - - return nil -} - -// NewDockerService creates a new `DockerService` struct. -// NOTE: Anything passed to DockerService should be eventually handled in another way when we switch to running the shim as a different process. -func NewDockerService(config *ClientConfig, podSandboxImage string, streamingConfig *streaming.Config, pluginSettings *NetworkPluginSettings, - cgroupsName string, kubeCgroupDriver string, dockershimRootDir string) (DockerService, error) { - - client := NewDockerClientFromConfig(config) - - c := libdocker.NewInstrumentedInterface(client) - - checkpointManager, err := checkpointmanager.NewCheckpointManager(filepath.Join(dockershimRootDir, sandboxCheckpointDir)) - if err != nil { - return nil, err - } - - ds := &dockerService{ - client: c, - os: kubecontainer.RealOS{}, - podSandboxImage: podSandboxImage, - streamingRuntime: &streamingRuntime{ - client: client, - execHandler: &NativeExecHandler{}, - }, - containerManager: cm.NewContainerManager(cgroupsName, client), - checkpointManager: checkpointManager, - networkReady: make(map[string]bool), - containerCleanupInfos: make(map[string]*containerCleanupInfo), - } - - // check docker version compatibility. - if err = ds.checkVersionCompatibility(); err != nil { - return nil, err - } - - // create streaming server if configured. - if streamingConfig != nil { - var err error - ds.streamingServer, err = streaming.NewServer(*streamingConfig, ds.streamingRuntime) - if err != nil { - return nil, err - } - } - - // Determine the hairpin mode. - if err := effectiveHairpinMode(pluginSettings); err != nil { - // This is a non-recoverable error. Returning it up the callstack will just - // lead to retries of the same failure, so just fail hard. - return nil, err - } - klog.InfoS("Hairpin mode is set", "hairpinMode", pluginSettings.HairpinMode) - - // dockershim currently only supports CNI plugins. - pluginSettings.PluginBinDirs = cni.SplitDirs(pluginSettings.PluginBinDirString) - cniPlugins := cni.ProbeNetworkPlugins(pluginSettings.PluginConfDir, pluginSettings.PluginCacheDir, pluginSettings.PluginBinDirs) - cniPlugins = append(cniPlugins, kubenet.NewPlugin(pluginSettings.PluginBinDirs, pluginSettings.PluginCacheDir)) - netHost := &dockerNetworkHost{ - &namespaceGetter{ds}, - &portMappingGetter{ds}, - } - plug, err := network.InitNetworkPlugin(cniPlugins, pluginSettings.PluginName, netHost, pluginSettings.HairpinMode, pluginSettings.NonMasqueradeCIDR, pluginSettings.MTU) - if err != nil { - return nil, fmt.Errorf("didn't find compatible CNI plugin with given settings %+v: %v", pluginSettings, err) - } - ds.network = network.NewPluginManager(plug) - klog.InfoS("Docker cri networking managed by the network plugin", "networkPluginName", plug.Name()) - - dockerInfo, err := ds.client.Info() - if err != nil { - return nil, fmt.Errorf("Failed to execute Info() call to the Docker client") - } - klog.InfoS("Docker Info", "dockerInfo", dockerInfo) - ds.dockerRootDir = dockerInfo.DockerRootDir - - // skipping cgroup driver checks for Windows - if runtime.GOOS == "linux" { - cgroupDriver := defaultCgroupDriver - if len(dockerInfo.CgroupDriver) == 0 { - klog.InfoS("No cgroup driver is set in Docker") - klog.InfoS("Falling back to use the default driver", "cgroupDriver", cgroupDriver) - } else { - cgroupDriver = dockerInfo.CgroupDriver - } - if len(kubeCgroupDriver) != 0 && kubeCgroupDriver != cgroupDriver { - return nil, fmt.Errorf("misconfiguration: kubelet cgroup driver: %q is different from docker cgroup driver: %q", kubeCgroupDriver, cgroupDriver) - } - klog.InfoS("Setting cgroupDriver", "cgroupDriver", cgroupDriver) - ds.cgroupDriver = cgroupDriver - } - - ds.versionCache = cache.NewObjectCache( - func() (interface{}, error) { - return ds.getDockerVersion() - }, - versionCacheTTL, - ) - - // Register prometheus metrics. - metrics.Register() - - return ds, nil -} - -type dockerService struct { - client libdocker.Interface - os kubecontainer.OSInterface - podSandboxImage string - streamingRuntime *streamingRuntime - streamingServer streaming.Server - - network *network.PluginManager - // Map of podSandboxID :: network-is-ready - networkReady map[string]bool - networkReadyLock sync.Mutex - - containerManager cm.ContainerManager - // cgroup driver used by Docker runtime. - cgroupDriver string - checkpointManager checkpointmanager.CheckpointManager - // caches the version of the runtime. - // To be compatible with multiple docker versions, we need to perform - // version checking for some operations. Use this cache to avoid querying - // the docker daemon every time we need to do such checks. - versionCache *cache.ObjectCache - - // docker root directory - dockerRootDir string - - // containerCleanupInfos maps container IDs to the `containerCleanupInfo` structs - // needed to clean up after containers have been removed. - // (see `applyPlatformSpecificDockerConfig` and `performPlatformSpecificContainerCleanup` - // methods for more info). - containerCleanupInfos map[string]*containerCleanupInfo - cleanupInfosLock sync.RWMutex -} - -// TODO: handle context. - -// Version returns the runtime name, runtime version and runtime API version -func (ds *dockerService) Version(_ context.Context, r *runtimeapi.VersionRequest) (*runtimeapi.VersionResponse, error) { - v, err := ds.getDockerVersion() - if err != nil { - return nil, err - } - return &runtimeapi.VersionResponse{ - Version: kubeAPIVersion, - RuntimeName: dockerRuntimeName, - RuntimeVersion: v.Version, - RuntimeApiVersion: v.APIVersion, - }, nil -} - -// getDockerVersion gets the version information from docker. -func (ds *dockerService) getDockerVersion() (*dockertypes.Version, error) { - v, err := ds.client.Version() - if err != nil { - return nil, fmt.Errorf("failed to get docker version: %v", err) - } - // Docker API version (e.g., 1.23) is not semver compatible. Add a ".0" - // suffix to remedy this. - v.APIVersion = fmt.Sprintf("%s.0", v.APIVersion) - return v, nil -} - -// UpdateRuntimeConfig updates the runtime config. Currently only handles podCIDR updates. -func (ds *dockerService) UpdateRuntimeConfig(_ context.Context, r *runtimeapi.UpdateRuntimeConfigRequest) (*runtimeapi.UpdateRuntimeConfigResponse, error) { - runtimeConfig := r.GetRuntimeConfig() - if runtimeConfig == nil { - return &runtimeapi.UpdateRuntimeConfigResponse{}, nil - } - - klog.InfoS("Docker cri received runtime config", "runtimeConfig", runtimeConfig) - if ds.network != nil && runtimeConfig.NetworkConfig.PodCidr != "" { - event := make(map[string]interface{}) - event[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = runtimeConfig.NetworkConfig.PodCidr - ds.network.Event(network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE, event) - } - - return &runtimeapi.UpdateRuntimeConfigResponse{}, nil -} - -// GetNetNS returns the network namespace of the given containerID. The ID -// supplied is typically the ID of a pod sandbox. This getter doesn't try -// to map non-sandbox IDs to their respective sandboxes. -func (ds *dockerService) GetNetNS(podSandboxID string) (string, error) { - r, err := ds.client.InspectContainer(podSandboxID) - if err != nil { - return "", err - } - return getNetworkNamespace(r) -} - -// GetPodPortMappings returns the port mappings of the given podSandbox ID. -func (ds *dockerService) GetPodPortMappings(podSandboxID string) ([]*hostport.PortMapping, error) { - // TODO: get portmappings from docker labels for backward compatibility - checkpoint := NewPodSandboxCheckpoint("", "", &CheckpointData{}) - err := ds.checkpointManager.GetCheckpoint(podSandboxID, checkpoint) - // Return empty portMappings if checkpoint is not found - if err != nil { - if err == errors.ErrCheckpointNotFound { - return nil, nil - } - errRem := ds.checkpointManager.RemoveCheckpoint(podSandboxID) - if errRem != nil { - klog.ErrorS(errRem, "Failed to delete corrupt checkpoint for sandbox", "podSandboxID", podSandboxID) - } - return nil, err - } - _, _, _, checkpointedPortMappings, _ := checkpoint.GetData() - portMappings := make([]*hostport.PortMapping, 0, len(checkpointedPortMappings)) - for _, pm := range checkpointedPortMappings { - proto := toAPIProtocol(*pm.Protocol) - portMappings = append(portMappings, &hostport.PortMapping{ - HostPort: *pm.HostPort, - ContainerPort: *pm.ContainerPort, - Protocol: proto, - HostIP: pm.HostIP, - }) - } - return portMappings, nil -} - -// Start initializes and starts components in dockerService. -func (ds *dockerService) Start() error { - ds.initCleanup() - - go func() { - if err := ds.streamingServer.Start(true); err != nil { - klog.ErrorS(err, "Streaming server stopped unexpectedly") - os.Exit(1) - } - }() - - return ds.containerManager.Start() -} - -// initCleanup is responsible for cleaning up any crufts left by previous -// runs. If there are any errors, it simply logs them. -func (ds *dockerService) initCleanup() { - errors := ds.platformSpecificContainerInitCleanup() - - for _, err := range errors { - klog.InfoS("Initialization error", "err", err) - } -} - -// Status returns the status of the runtime. -func (ds *dockerService) Status(_ context.Context, r *runtimeapi.StatusRequest) (*runtimeapi.StatusResponse, error) { - runtimeReady := &runtimeapi.RuntimeCondition{ - Type: runtimeapi.RuntimeReady, - Status: true, - } - networkReady := &runtimeapi.RuntimeCondition{ - Type: runtimeapi.NetworkReady, - Status: true, - } - conditions := []*runtimeapi.RuntimeCondition{runtimeReady, networkReady} - if _, err := ds.client.Version(); err != nil { - runtimeReady.Status = false - runtimeReady.Reason = "DockerDaemonNotReady" - runtimeReady.Message = fmt.Sprintf("docker: failed to get docker version: %v", err) - } - if err := ds.network.Status(); err != nil { - networkReady.Status = false - networkReady.Reason = "NetworkPluginNotReady" - networkReady.Message = fmt.Sprintf("docker: network plugin is not ready: %v", err) - } - status := &runtimeapi.RuntimeStatus{Conditions: conditions} - return &runtimeapi.StatusResponse{Status: status}, nil -} - -func (ds *dockerService) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if ds.streamingServer != nil { - ds.streamingServer.ServeHTTP(w, r) - } else { - http.NotFound(w, r) - } -} - -// GenerateExpectedCgroupParent returns cgroup parent in syntax expected by cgroup driver -func (ds *dockerService) GenerateExpectedCgroupParent(cgroupParent string) (string, error) { - if cgroupParent != "" { - // if docker uses the systemd cgroup driver, it expects *.slice style names for cgroup parent. - // if we configured kubelet to use --cgroup-driver=cgroupfs, and docker is configured to use systemd driver - // docker will fail to launch the container because the name we provide will not be a valid slice. - // this is a very good thing. - if ds.cgroupDriver == "systemd" { - // Pass only the last component of the cgroup path to systemd. - cgroupParent = path.Base(cgroupParent) - } - } - klog.V(3).InfoS("Setting cgroup parent", "cgroupParent", cgroupParent) - return cgroupParent, nil -} - -// checkVersionCompatibility verifies whether docker is in a compatible version. -func (ds *dockerService) checkVersionCompatibility() error { - apiVersion, err := ds.getDockerAPIVersion() - if err != nil { - return err - } - - minAPIVersion, err := semver.Parse(libdocker.MinimumDockerAPIVersion) - if err != nil { - return err - } - - // Verify the docker version. - result := apiVersion.Compare(minAPIVersion) - if result < 0 { - return fmt.Errorf("docker API version is older than %s", libdocker.MinimumDockerAPIVersion) - } - - return nil -} - -// getDockerAPIVersion gets the semver-compatible docker api version. -func (ds *dockerService) getDockerAPIVersion() (*semver.Version, error) { - var dv *dockertypes.Version - var err error - if ds.versionCache != nil { - dv, err = ds.getDockerVersionFromCache() - } else { - dv, err = ds.getDockerVersion() - } - if err != nil { - return nil, err - } - - apiVersion, err := semver.Parse(dv.APIVersion) - if err != nil { - return nil, err - } - return &apiVersion, nil -} - -func (ds *dockerService) getDockerVersionFromCache() (*dockertypes.Version, error) { - // We only store on key in the cache. - const dummyKey = "version" - value, err := ds.versionCache.Get(dummyKey) - if err != nil { - return nil, err - } - dv, ok := value.(*dockertypes.Version) - if !ok { - return nil, fmt.Errorf("converted to *dockertype.Version error") - } - return dv, nil -} - -func toAPIProtocol(protocol Protocol) v1.Protocol { - switch protocol { - case protocolTCP: - return v1.ProtocolTCP - case protocolUDP: - return v1.ProtocolUDP - case protocolSCTP: - return v1.ProtocolSCTP - } - klog.InfoS("Unknown protocol, defaulting to TCP", "protocol", protocol) - return v1.ProtocolTCP -} - -// effectiveHairpinMode determines the effective hairpin mode given the -// configured mode, and whether cbr0 should be configured. -func effectiveHairpinMode(s *NetworkPluginSettings) error { - // The hairpin mode setting doesn't matter if: - // - We're not using a bridge network. This is hard to check because we might - // be using a plugin. - // - It's set to hairpin-veth for a container runtime that doesn't know how - // to set the hairpin flag on the veth's of containers. Currently the - // docker runtime is the only one that understands this. - // - It's set to "none". - if s.HairpinMode == kubeletconfig.PromiscuousBridge || s.HairpinMode == kubeletconfig.HairpinVeth { - if s.HairpinMode == kubeletconfig.PromiscuousBridge && s.PluginName != "kubenet" { - // This is not a valid combination, since promiscuous-bridge only works on kubenet. Users might be using the - // default values (from before the hairpin-mode flag existed) and we - // should keep the old behavior. - klog.InfoS("Hairpin mode is set but kubenet is not enabled, falling back to HairpinVeth", "hairpinMode", s.HairpinMode) - s.HairpinMode = kubeletconfig.HairpinVeth - return nil - } - } else if s.HairpinMode != kubeletconfig.HairpinNone { - return fmt.Errorf("unknown value: %q", s.HairpinMode) - } - return nil -} diff --git a/pkg/kubelet/dockershim/docker_service_test.go b/pkg/kubelet/dockershim/docker_service_test.go deleted file mode 100644 index 6f89594b69e..00000000000 --- a/pkg/kubelet/dockershim/docker_service_test.go +++ /dev/null @@ -1,171 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "errors" - "math/rand" - "testing" - "time" - - "github.com/blang/semver" - dockertypes "github.com/docker/docker/api/types" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" - containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - nettest "k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing" - "k8s.io/kubernetes/pkg/kubelet/util/cache" - testingclock "k8s.io/utils/clock/testing" -) - -type mockCheckpointManager struct { - checkpoint map[string]*PodSandboxCheckpoint -} - -func (ckm *mockCheckpointManager) CreateCheckpoint(checkpointKey string, checkpoint checkpointmanager.Checkpoint) error { - ckm.checkpoint[checkpointKey] = checkpoint.(*PodSandboxCheckpoint) - return nil -} - -func (ckm *mockCheckpointManager) GetCheckpoint(checkpointKey string, checkpoint checkpointmanager.Checkpoint) error { - *(checkpoint.(*PodSandboxCheckpoint)) = *(ckm.checkpoint[checkpointKey]) - return nil -} - -func (ckm *mockCheckpointManager) RemoveCheckpoint(checkpointKey string) error { - _, ok := ckm.checkpoint[checkpointKey] - if ok { - delete(ckm.checkpoint, "moo") - } - return nil -} - -func (ckm *mockCheckpointManager) ListCheckpoints() ([]string, error) { - var keys []string - for key := range ckm.checkpoint { - keys = append(keys, key) - } - return keys, nil -} - -func newMockCheckpointManager() checkpointmanager.CheckpointManager { - return &mockCheckpointManager{checkpoint: make(map[string]*PodSandboxCheckpoint)} -} - -func newTestDockerService() (*dockerService, *libdocker.FakeDockerClient, *testingclock.FakeClock) { - fakeClock := testingclock.NewFakeClock(time.Time{}) - c := libdocker.NewFakeDockerClient().WithClock(fakeClock).WithVersion("1.11.2", "1.23").WithRandSource(rand.NewSource(0)) - pm := network.NewPluginManager(&network.NoopNetworkPlugin{}) - ckm := newMockCheckpointManager() - return &dockerService{ - client: c, - os: &containertest.FakeOS{}, - network: pm, - checkpointManager: ckm, - networkReady: make(map[string]bool), - dockerRootDir: "/docker/root/dir", - }, c, fakeClock -} - -func newTestDockerServiceWithVersionCache() (*dockerService, *libdocker.FakeDockerClient, *testingclock.FakeClock) { - ds, c, fakeClock := newTestDockerService() - ds.versionCache = cache.NewObjectCache( - func() (interface{}, error) { - return ds.getDockerVersion() - }, - time.Hour*10, - ) - return ds, c, fakeClock -} - -// TestStatus tests the runtime status logic. -func TestStatus(t *testing.T) { - ds, fDocker, _ := newTestDockerService() - - assertStatus := func(expected map[string]bool, status *runtimeapi.RuntimeStatus) { - conditions := status.GetConditions() - assert.Equal(t, len(expected), len(conditions)) - for k, v := range expected { - for _, c := range conditions { - if k == c.Type { - assert.Equal(t, v, c.Status) - } - } - } - } - - // Should report ready status if version returns no error. - statusResp, err := ds.Status(getTestCTX(), &runtimeapi.StatusRequest{}) - require.NoError(t, err) - assertStatus(map[string]bool{ - runtimeapi.RuntimeReady: true, - runtimeapi.NetworkReady: true, - }, statusResp.Status) - - // Should not report ready status if version returns error. - fDocker.InjectError("version", errors.New("test error")) - statusResp, err = ds.Status(getTestCTX(), &runtimeapi.StatusRequest{}) - assert.NoError(t, err) - assertStatus(map[string]bool{ - runtimeapi.RuntimeReady: false, - runtimeapi.NetworkReady: true, - }, statusResp.Status) - - // Should not report ready status is network plugin returns error. - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockPlugin := nettest.NewMockNetworkPlugin(ctrl) - ds.network = network.NewPluginManager(mockPlugin) - mockPlugin.EXPECT().Status().Return(errors.New("network error")) - statusResp, err = ds.Status(getTestCTX(), &runtimeapi.StatusRequest{}) - assert.NoError(t, err) - assertStatus(map[string]bool{ - runtimeapi.RuntimeReady: true, - runtimeapi.NetworkReady: false, - }, statusResp.Status) -} - -func TestVersion(t *testing.T) { - ds, _, _ := newTestDockerService() - - expectedVersion := &dockertypes.Version{Version: "1.11.2", APIVersion: "1.23.0"} - v, err := ds.getDockerVersion() - require.NoError(t, err) - assert.Equal(t, expectedVersion, v) - - expectedAPIVersion := &semver.Version{Major: 1, Minor: 23, Patch: 0} - apiVersion, err := ds.getDockerAPIVersion() - require.NoError(t, err) - assert.Equal(t, expectedAPIVersion, apiVersion) -} - -func TestAPIVersionWithCache(t *testing.T) { - ds, _, _ := newTestDockerServiceWithVersionCache() - - expected := &semver.Version{Major: 1, Minor: 23, Patch: 0} - version, err := ds.getDockerAPIVersion() - require.NoError(t, err) - assert.Equal(t, expected, version) -} diff --git a/pkg/kubelet/dockershim/docker_stats.go b/pkg/kubelet/dockershim/docker_stats.go deleted file mode 100644 index e673bcd1170..00000000000 --- a/pkg/kubelet/dockershim/docker_stats.go +++ /dev/null @@ -1,91 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "errors" - "fmt" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -var ErrNotImplemented = errors.New("Not implemented") - -// ContainerStats returns stats for a container stats request based on container id. -func (ds *dockerService) ContainerStats(ctx context.Context, r *runtimeapi.ContainerStatsRequest) (*runtimeapi.ContainerStatsResponse, error) { - filter := &runtimeapi.ContainerFilter{ - Id: r.ContainerId, - } - listResp, err := ds.ListContainers(ctx, &runtimeapi.ListContainersRequest{Filter: filter}) - if err != nil { - return nil, err - } - if len(listResp.Containers) != 1 { - return nil, fmt.Errorf("container with id %s not found", r.ContainerId) - } - stats, err := ds.getContainerStats(listResp.Containers[0]) - if err != nil { - return nil, err - } - return &runtimeapi.ContainerStatsResponse{Stats: stats}, nil -} - -// ListContainerStats returns stats for a list container stats request based on a filter. -func (ds *dockerService) ListContainerStats(ctx context.Context, r *runtimeapi.ListContainerStatsRequest) (*runtimeapi.ListContainerStatsResponse, error) { - containerStatsFilter := r.GetFilter() - filter := &runtimeapi.ContainerFilter{} - - if containerStatsFilter != nil { - filter.Id = containerStatsFilter.Id - filter.PodSandboxId = containerStatsFilter.PodSandboxId - filter.LabelSelector = containerStatsFilter.LabelSelector - } - - listResp, err := ds.ListContainers(ctx, &runtimeapi.ListContainersRequest{Filter: filter}) - if err != nil { - return nil, err - } - - var stats []*runtimeapi.ContainerStats - for _, container := range listResp.Containers { - containerStats, err := ds.getContainerStats(container) - if err != nil { - return nil, err - } - if containerStats != nil { - stats = append(stats, containerStats) - } - } - - return &runtimeapi.ListContainerStatsResponse{Stats: stats}, nil -} - -// PodSandboxStats returns stats for a pod sandbox based on pod sandbox id. -// This function is not implemented for the dockershim. -func (ds *dockerService) PodSandboxStats(_ context.Context, r *runtimeapi.PodSandboxStatsRequest) (*runtimeapi.PodSandboxStatsResponse, error) { - return nil, ErrNotImplemented -} - -// ListPodSandboxStats returns stats for a list of pod sandboxes based on a filter. -// This function is not implemented for the dockershim. -func (ds *dockerService) ListPodSandboxStats(ctx context.Context, r *runtimeapi.ListPodSandboxStatsRequest) (*runtimeapi.ListPodSandboxStatsResponse, error) { - return nil, ErrNotImplemented -} diff --git a/pkg/kubelet/dockershim/docker_stats_linux.go b/pkg/kubelet/dockershim/docker_stats_linux.go deleted file mode 100644 index b7be67a6fe4..00000000000 --- a/pkg/kubelet/dockershim/docker_stats_linux.go +++ /dev/null @@ -1,63 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "time" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -func (ds *dockerService) getContainerStats(c *runtimeapi.Container) (*runtimeapi.ContainerStats, error) { - statsJSON, err := ds.client.GetContainerStats(c.Id) - if err != nil { - return nil, err - } - - containerJSON, err := ds.client.InspectContainerWithSize(c.Id) - if err != nil { - return nil, err - } - - dockerStats := statsJSON.Stats - timestamp := time.Now().UnixNano() - containerStats := &runtimeapi.ContainerStats{ - Attributes: &runtimeapi.ContainerAttributes{ - Id: c.Id, - Metadata: c.Metadata, - Labels: c.Labels, - Annotations: c.Annotations, - }, - Cpu: &runtimeapi.CpuUsage{ - Timestamp: timestamp, - UsageCoreNanoSeconds: &runtimeapi.UInt64Value{Value: dockerStats.CPUStats.CPUUsage.TotalUsage}, - }, - Memory: &runtimeapi.MemoryUsage{ - Timestamp: timestamp, - WorkingSetBytes: &runtimeapi.UInt64Value{Value: dockerStats.MemoryStats.PrivateWorkingSet}, - }, - WritableLayer: &runtimeapi.FilesystemUsage{ - Timestamp: timestamp, - FsId: &runtimeapi.FilesystemIdentifier{Mountpoint: ds.dockerRootDir}, - UsedBytes: &runtimeapi.UInt64Value{Value: uint64(*containerJSON.SizeRw)}, - }, - } - return containerStats, nil -} diff --git a/pkg/kubelet/dockershim/docker_stats_test.go b/pkg/kubelet/dockershim/docker_stats_test.go deleted file mode 100644 index a26743aa7d3..00000000000 --- a/pkg/kubelet/dockershim/docker_stats_test.go +++ /dev/null @@ -1,82 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "testing" - - dockertypes "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/stretchr/testify/assert" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -func TestContainerStats(t *testing.T) { - labels := map[string]string{containerTypeLabelKey: containerTypeLabelContainer} - tests := map[string]struct { - containerID string - container *libdocker.FakeContainer - containerStats *dockertypes.StatsJSON - calledDetails []libdocker.CalledDetail - }{ - "container exists": { - "k8s_fake_container", - &libdocker.FakeContainer{ - ID: "k8s_fake_container", - Name: "k8s_fake_container_1_2_1", - Config: &container.Config{ - Labels: labels, - }, - }, - &dockertypes.StatsJSON{}, - []libdocker.CalledDetail{ - libdocker.NewCalledDetail("list", nil), - libdocker.NewCalledDetail("get_container_stats", nil), - libdocker.NewCalledDetail("inspect_container_withsize", nil), - }, - }, - "container doesn't exists": { - "k8s_nonexistant_fake_container", - &libdocker.FakeContainer{ - ID: "k8s_fake_container", - Name: "k8s_fake_container_1_2_1", - Config: &container.Config{ - Labels: labels, - }, - }, - &dockertypes.StatsJSON{}, - []libdocker.CalledDetail{ - libdocker.NewCalledDetail("list", nil), - }, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - ds, fakeDocker, _ := newTestDockerService() - fakeDocker.SetFakeContainers([]*libdocker.FakeContainer{test.container}) - fakeDocker.InjectContainerStats(map[string]*dockertypes.StatsJSON{test.container.ID: test.containerStats}) - ds.ContainerStats(getTestCTX(), &runtimeapi.ContainerStatsRequest{ContainerId: test.containerID}) - err := fakeDocker.AssertCallDetails(test.calledDetails...) - assert.NoError(t, err) - }) - } -} diff --git a/pkg/kubelet/dockershim/docker_stats_unsupported.go b/pkg/kubelet/dockershim/docker_stats_unsupported.go deleted file mode 100644 index 1f3f5747a4b..00000000000 --- a/pkg/kubelet/dockershim/docker_stats_unsupported.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build !linux && !windows && !dockerless -// +build !linux,!windows,!dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -func (ds *dockerService) getContainerStats(c *runtimeapi.Container) (*runtimeapi.ContainerStats, error) { - return nil, fmt.Errorf("not implemented") -} diff --git a/pkg/kubelet/dockershim/docker_stats_windows.go b/pkg/kubelet/dockershim/docker_stats_windows.go deleted file mode 100644 index df9f0b37597..00000000000 --- a/pkg/kubelet/dockershim/docker_stats_windows.go +++ /dev/null @@ -1,91 +0,0 @@ -//go:build windows && !dockerless -// +build windows,!dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "strings" - "time" - - "github.com/Microsoft/hcsshim" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/klog/v2" -) - -func (ds *dockerService) getContainerStats(c *runtimeapi.Container) (*runtimeapi.ContainerStats, error) { - hcsshimContainer, err := hcsshim.OpenContainer(c.Id) - if err != nil { - // As we moved from using Docker stats to hcsshim directly, we may query HCS with already exited container IDs. - // That will typically happen with init-containers in Exited state. Docker still knows about them but the HCS does not. - // As we don't want to block stats retrieval for other containers, we only log errors. - if !hcsshim.IsNotExist(err) && !hcsshim.IsAlreadyStopped(err) { - klog.V(4).InfoS("Error opening container (stats will be missing)", "containerID", c.Id, "err", err) - } - return nil, nil - } - defer func() { - closeErr := hcsshimContainer.Close() - if closeErr != nil { - klog.ErrorS(closeErr, "Error closing container", "containerID", c.Id) - } - }() - - stats, err := hcsshimContainer.Statistics() - if err != nil { - if strings.Contains(err.Error(), "0x5") || strings.Contains(err.Error(), "0xc0370105") { - // When the container is just created, querying for stats causes access errors because it hasn't started yet - // This is transient; skip container for now - // - // These hcs errors do not have helpers exposed in public package so need to query for the known codes - // https://github.com/microsoft/hcsshim/blob/master/internal/hcs/errors.go - // PR to expose helpers in hcsshim: https://github.com/microsoft/hcsshim/pull/933 - klog.V(4).InfoS("Container is not in a state that stats can be accessed. This occurs when the container is created but not started.", "containerID", c.Id, "err", err) - return nil, nil - } - return nil, err - } - - timestamp := time.Now().UnixNano() - containerStats := &runtimeapi.ContainerStats{ - Attributes: &runtimeapi.ContainerAttributes{ - Id: c.Id, - Metadata: c.Metadata, - Labels: c.Labels, - Annotations: c.Annotations, - }, - Cpu: &runtimeapi.CpuUsage{ - Timestamp: timestamp, - // have to multiply cpu usage by 100 since stats units is in 100's of nano seconds for Windows - UsageCoreNanoSeconds: &runtimeapi.UInt64Value{Value: stats.Processor.TotalRuntime100ns * 100}, - }, - Memory: &runtimeapi.MemoryUsage{ - Timestamp: timestamp, - WorkingSetBytes: &runtimeapi.UInt64Value{Value: stats.Memory.UsagePrivateWorkingSetBytes}, - }, - WritableLayer: &runtimeapi.FilesystemUsage{ - Timestamp: timestamp, - FsId: &runtimeapi.FilesystemIdentifier{Mountpoint: ds.dockerRootDir}, - // used bytes from image are not implemented on Windows - // don't query for it since it is expensive to call docker over named pipe - // https://github.com/moby/moby/blob/1ba54a5fd0ba293db3bea46cd67604b593f2048b/daemon/images/image_windows.go#L11-L14 - UsedBytes: &runtimeapi.UInt64Value{Value: 0}, - }, - } - return containerStats, nil -} diff --git a/pkg/kubelet/dockershim/docker_streaming.go b/pkg/kubelet/dockershim/docker_streaming.go deleted file mode 100644 index 106a5ff1f43..00000000000 --- a/pkg/kubelet/dockershim/docker_streaming.go +++ /dev/null @@ -1,209 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "bytes" - "context" - "errors" - "fmt" - "io" - "math" - "time" - "unsafe" - - dockertypes "github.com/docker/docker/api/types" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "k8s.io/client-go/tools/remotecommand" - runtimeapiv1 "k8s.io/cri-api/pkg/apis/runtime/v1" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/cri/streaming" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/util/ioutils" - utilexec "k8s.io/utils/exec" -) - -type streamingRuntime struct { - client libdocker.Interface - execHandler ExecHandler -} - -var _ streaming.Runtime = &streamingRuntime{} - -const maxMsgSize = 1024 * 1024 * 16 - -func (r *streamingRuntime) Exec(containerID string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - return r.exec(context.TODO(), containerID, cmd, in, out, err, tty, resize, 0) -} - -// Internal version of Exec adds a timeout. -func (r *streamingRuntime) exec(ctx context.Context, containerID string, cmd []string, in io.Reader, out, errw io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - container, err := checkContainerStatus(r.client, containerID) - if err != nil { - return err - } - - return r.execHandler.ExecInContainer(ctx, r.client, container, cmd, in, out, errw, tty, resize, timeout) -} - -func (r *streamingRuntime) Attach(containerID string, in io.Reader, out, errw io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - _, err := checkContainerStatus(r.client, containerID) - if err != nil { - return err - } - - return attachContainer(r.client, containerID, in, out, errw, tty, resize) -} - -func (r *streamingRuntime) PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error { - if port < 0 || port > math.MaxUint16 { - return fmt.Errorf("invalid port %d", port) - } - return r.portForward(podSandboxID, port, stream) -} - -// ExecSync executes a command in the container, and returns the stdout output. -// If command exits with a non-zero exit code, an error is returned. -func (ds *dockerService) ExecSync(ctx context.Context, req *runtimeapi.ExecSyncRequest) (*runtimeapi.ExecSyncResponse, error) { - timeout := time.Duration(req.Timeout) * time.Second - var stdoutBuffer, stderrBuffer bytes.Buffer - err := ds.streamingRuntime.exec(ctx, req.ContainerId, req.Cmd, - nil, // in - ioutils.WriteCloserWrapper(ioutils.LimitWriter(&stdoutBuffer, maxMsgSize)), - ioutils.WriteCloserWrapper(ioutils.LimitWriter(&stderrBuffer, maxMsgSize)), - false, // tty - nil, // resize - timeout) - - // kubelet's remote runtime expects a grpc error with status code DeadlineExceeded on time out. - if errors.Is(err, context.DeadlineExceeded) { - return nil, status.Errorf(codes.DeadlineExceeded, err.Error()) - } - - var exitCode int32 - if err != nil { - exitError, ok := err.(utilexec.ExitError) - if !ok { - return nil, err - } - - exitCode = int32(exitError.ExitStatus()) - } - return &runtimeapi.ExecSyncResponse{ - Stdout: stdoutBuffer.Bytes(), - Stderr: stderrBuffer.Bytes(), - ExitCode: exitCode, - }, nil -} - -// Exec prepares a streaming endpoint to execute a command in the container, and returns the address. -func (ds *dockerService) Exec(_ context.Context, req *runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error) { - if ds.streamingServer == nil { - return nil, streaming.NewErrorStreamingDisabled("exec") - } - _, err := checkContainerStatus(ds.client, req.ContainerId) - if err != nil { - return nil, err - } - // This conversion has been copied from the functions in - // pkg/kubelet/cri/remote/conversion.go - r := (*runtimeapiv1.ExecRequest)(unsafe.Pointer(req)) - resp, err := ds.streamingServer.GetExec(r) - if err != nil { - return nil, err - } - return (*runtimeapi.ExecResponse)(unsafe.Pointer(resp)), nil -} - -// Attach prepares a streaming endpoint to attach to a running container, and returns the address. -func (ds *dockerService) Attach(_ context.Context, req *runtimeapi.AttachRequest) (*runtimeapi.AttachResponse, error) { - if ds.streamingServer == nil { - return nil, streaming.NewErrorStreamingDisabled("attach") - } - _, err := checkContainerStatus(ds.client, req.ContainerId) - if err != nil { - return nil, err - } - // This conversion has been copied from the functions in - // pkg/kubelet/cri/remote/conversion.go - r := (*runtimeapiv1.AttachRequest)(unsafe.Pointer(req)) - resp, err := ds.streamingServer.GetAttach(r) - if err != nil { - return nil, err - } - return (*runtimeapi.AttachResponse)(unsafe.Pointer(resp)), nil -} - -// PortForward prepares a streaming endpoint to forward ports from a PodSandbox, and returns the address. -func (ds *dockerService) PortForward(_ context.Context, req *runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error) { - if ds.streamingServer == nil { - return nil, streaming.NewErrorStreamingDisabled("port forward") - } - _, err := checkContainerStatus(ds.client, req.PodSandboxId) - if err != nil { - return nil, err - } - // TODO(tallclair): Verify that ports are exposed. - // This conversion has been copied from the functions in - // pkg/kubelet/cri/remote/conversion.go - r := (*runtimeapiv1.PortForwardRequest)(unsafe.Pointer(req)) - resp, err := ds.streamingServer.GetPortForward(r) - if err != nil { - return nil, err - } - return (*runtimeapi.PortForwardResponse)(unsafe.Pointer(resp)), nil -} - -func checkContainerStatus(client libdocker.Interface, containerID string) (*dockertypes.ContainerJSON, error) { - container, err := client.InspectContainer(containerID) - if err != nil { - return nil, err - } - if !container.State.Running { - return nil, fmt.Errorf("container not running (%s)", container.ID) - } - return container, nil -} - -func attachContainer(client libdocker.Interface, containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - // Have to start this before the call to client.AttachToContainer because client.AttachToContainer is a blocking - // call :-( Otherwise, resize events don't get processed and the terminal never resizes. - kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) { - client.ResizeContainerTTY(containerID, uint(size.Height), uint(size.Width)) - }) - - // TODO(random-liu): Do we really use the *Logs* field here? - opts := dockertypes.ContainerAttachOptions{ - Stream: true, - Stdin: stdin != nil, - Stdout: stdout != nil, - Stderr: stderr != nil, - } - sopts := libdocker.StreamOptions{ - InputStream: stdin, - OutputStream: stdout, - ErrorStream: stderr, - RawTerminal: tty, - } - return client.AttachToContainer(containerID, opts, sopts) -} diff --git a/pkg/kubelet/dockershim/docker_streaming_others.go b/pkg/kubelet/dockershim/docker_streaming_others.go deleted file mode 100644 index eb041c1073c..00000000000 --- a/pkg/kubelet/dockershim/docker_streaming_others.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build !windows && !dockerless -// +build !windows,!dockerless - -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "bytes" - "fmt" - "io" - "os/exec" - "strings" - - "k8s.io/klog/v2" -) - -func (r *streamingRuntime) portForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error { - container, err := r.client.InspectContainer(podSandboxID) - if err != nil { - return err - } - - if !container.State.Running { - return fmt.Errorf("container not running (%s)", container.ID) - } - - containerPid := container.State.Pid - socatPath, lookupErr := exec.LookPath("socat") - if lookupErr != nil { - return fmt.Errorf("unable to do port forwarding: socat not found") - } - - args := []string{"-t", fmt.Sprintf("%d", containerPid), "-n", socatPath, "-", fmt.Sprintf("TCP4:localhost:%d", port)} - - nsenterPath, lookupErr := exec.LookPath("nsenter") - if lookupErr != nil { - return fmt.Errorf("unable to do port forwarding: nsenter not found") - } - - commandString := fmt.Sprintf("%s %s", nsenterPath, strings.Join(args, " ")) - klog.V(4).InfoS("Executing port forwarding command", "command", commandString) - - command := exec.Command(nsenterPath, args...) - command.Stdout = stream - - stderr := new(bytes.Buffer) - command.Stderr = stderr - - // If we use Stdin, command.Run() won't return until the goroutine that's copying - // from stream finishes. Unfortunately, if you have a client like telnet connected - // via port forwarding, as long as the user's telnet client is connected to the user's - // local listener that port forwarding sets up, the telnet session never exits. This - // means that even if socat has finished running, command.Run() won't ever return - // (because the client still has the connection and stream open). - // - // The work around is to use StdinPipe(), as Wait() (called by Run()) closes the pipe - // when the command (socat) exits. - inPipe, err := command.StdinPipe() - if err != nil { - return fmt.Errorf("unable to do port forwarding: error creating stdin pipe: %v", err) - } - go func() { - io.Copy(inPipe, stream) - inPipe.Close() - }() - - if err := command.Run(); err != nil { - return fmt.Errorf("%v: %s", err, stderr.String()) - } - - return nil -} diff --git a/pkg/kubelet/dockershim/docker_streaming_windows.go b/pkg/kubelet/dockershim/docker_streaming_windows.go deleted file mode 100644 index cad09a9980d..00000000000 --- a/pkg/kubelet/dockershim/docker_streaming_windows.go +++ /dev/null @@ -1,39 +0,0 @@ -//go:build windows && !dockerless -// +build windows,!dockerless - -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "bytes" - "context" - "fmt" - "io" - - "k8s.io/kubernetes/pkg/kubelet/util/ioutils" -) - -func (r *streamingRuntime) portForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error { - stderr := new(bytes.Buffer) - err := r.exec(context.TODO(), podSandboxID, []string{"wincat.exe", "127.0.0.1", fmt.Sprint(port)}, stream, stream, ioutils.WriteCloserWrapper(stderr), false, nil, 0) - if err != nil { - return fmt.Errorf("%v: %s", err, stderr.String()) - } - - return nil -} diff --git a/pkg/kubelet/dockershim/dockershim_nodocker.go b/pkg/kubelet/dockershim/dockershim_nodocker.go deleted file mode 100644 index 9cb89fa7906..00000000000 --- a/pkg/kubelet/dockershim/dockershim_nodocker.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build dockerless -// +build dockerless - -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim diff --git a/pkg/kubelet/dockershim/exec.go b/pkg/kubelet/dockershim/exec.go deleted file mode 100644 index 6c8aac5989e..00000000000 --- a/pkg/kubelet/dockershim/exec.go +++ /dev/null @@ -1,162 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "fmt" - "io" - "time" - - dockertypes "github.com/docker/docker/api/types" - - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/tools/remotecommand" - "k8s.io/klog/v2" - "k8s.io/kubernetes/pkg/features" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -// ExecHandler knows how to execute a command in a running Docker container. -type ExecHandler interface { - ExecInContainer(ctx context.Context, client libdocker.Interface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error -} - -type dockerExitError struct { - Inspect *dockertypes.ContainerExecInspect -} - -func (d *dockerExitError) String() string { - return d.Error() -} - -func (d *dockerExitError) Error() string { - return fmt.Sprintf("Error executing in Docker Container: %d", d.Inspect.ExitCode) -} - -func (d *dockerExitError) Exited() bool { - return !d.Inspect.Running -} - -func (d *dockerExitError) ExitStatus() int { - return d.Inspect.ExitCode -} - -// NativeExecHandler executes commands in Docker containers using Docker's exec API. -type NativeExecHandler struct{} - -// ExecInContainer executes the cmd in container using the Docker's exec API -func (*NativeExecHandler) ExecInContainer(ctx context.Context, client libdocker.Interface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error { - done := make(chan struct{}) - defer close(done) - - createOpts := dockertypes.ExecConfig{ - Cmd: cmd, - AttachStdin: stdin != nil, - AttachStdout: stdout != nil, - AttachStderr: stderr != nil, - Tty: tty, - } - execObj, err := client.CreateExec(container.ID, createOpts) - if err != nil { - return fmt.Errorf("failed to exec in container - Exec setup failed - %v", err) - } - - // Have to start this before the call to client.StartExec because client.StartExec is a blocking - // call :-( Otherwise, resize events don't get processed and the terminal never resizes. - // - // We also have to delay attempting to send a terminal resize request to docker until after the - // exec has started; otherwise, the initial resize request will fail. - execStarted := make(chan struct{}) - go func() { - select { - case <-execStarted: - // client.StartExec has started the exec, so we can start resizing - case <-done: - // ExecInContainer has returned, so short-circuit - return - } - - kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) { - client.ResizeExecTTY(execObj.ID, uint(size.Height), uint(size.Width)) - }) - }() - - startOpts := dockertypes.ExecStartCheck{Detach: false, Tty: tty} - streamOpts := libdocker.StreamOptions{ - InputStream: stdin, - OutputStream: stdout, - ErrorStream: stderr, - RawTerminal: tty, - ExecStarted: execStarted, - } - - if timeout > 0 && utilfeature.DefaultFeatureGate.Enabled(features.ExecProbeTimeout) { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, timeout) - defer cancel() - } - - // StartExec is a blocking call, so we need to run it concurrently and catch - // its error in a channel - execErr := make(chan error, 1) - go func() { - execErr <- client.StartExec(execObj.ID, startOpts, streamOpts) - }() - - select { - case <-ctx.Done(): - return ctx.Err() - case err := <-execErr: - if err != nil { - return err - } - } - - // InspectExec may not always return latest state of exec, so call it a few times until - // it returns an exec inspect that shows that the process is no longer running. - retries := 0 - maxRetries := 5 - ticker := time.NewTicker(2 * time.Second) - defer ticker.Stop() - for { - inspect, err := client.InspectExec(execObj.ID) - if err != nil { - return err - } - - if !inspect.Running { - if inspect.ExitCode != 0 { - return &dockerExitError{inspect} - } - - return nil - } - - retries++ - if retries == maxRetries { - klog.ErrorS(nil, "Exec session in the container terminated but process still running!", "execSession", execObj.ID, "containerID", container.ID) - return nil - } - - <-ticker.C - } -} diff --git a/pkg/kubelet/dockershim/exec_test.go b/pkg/kubelet/dockershim/exec_test.go deleted file mode 100644 index 184ccf8f032..00000000000 --- a/pkg/kubelet/dockershim/exec_test.go +++ /dev/null @@ -1,191 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "context" - "fmt" - "io" - "testing" - "time" - - dockertypes "github.com/docker/docker/api/types" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/tools/remotecommand" - featuregatetesting "k8s.io/component-base/featuregate/testing" - "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - mockclient "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker/testing" -) - -func TestExecInContainer(t *testing.T) { - - testcases := []struct { - description string - timeout time.Duration - returnCreateExec1 *dockertypes.IDResponse - returnCreateExec2 error - returnStartExec error - returnInspectExec1 *dockertypes.ContainerExecInspect - returnInspectExec2 error - execProbeTimeout bool - startExecDelay time.Duration - expectError error - }{{ - description: "ExecInContainer succeeds", - timeout: time.Minute, - returnCreateExec1: &dockertypes.IDResponse{ID: "12345678"}, - returnCreateExec2: nil, - returnStartExec: nil, - returnInspectExec1: &dockertypes.ContainerExecInspect{ - ExecID: "200", - ContainerID: "12345678", - Running: false, - ExitCode: 0, - Pid: 100}, - returnInspectExec2: nil, - execProbeTimeout: true, - expectError: nil, - }, { - description: "CreateExec returns an error", - timeout: time.Minute, - returnCreateExec1: nil, - returnCreateExec2: fmt.Errorf("error in CreateExec()"), - returnStartExec: nil, - returnInspectExec1: nil, - returnInspectExec2: nil, - execProbeTimeout: true, - expectError: fmt.Errorf("failed to exec in container - Exec setup failed - error in CreateExec()"), - }, { - description: "StartExec returns an error", - timeout: time.Minute, - returnCreateExec1: &dockertypes.IDResponse{ID: "12345678"}, - returnCreateExec2: nil, - returnStartExec: fmt.Errorf("error in StartExec()"), - returnInspectExec1: nil, - returnInspectExec2: nil, - execProbeTimeout: true, - expectError: fmt.Errorf("error in StartExec()"), - }, { - description: "InspectExec returns an error", - timeout: time.Minute, - returnCreateExec1: &dockertypes.IDResponse{ID: "12345678"}, - returnCreateExec2: nil, - returnStartExec: nil, - returnInspectExec1: nil, - returnInspectExec2: fmt.Errorf("error in InspectExec()"), - execProbeTimeout: true, - expectError: fmt.Errorf("error in InspectExec()"), - }, { - description: "ExecInContainer returns context DeadlineExceeded", - timeout: 1 * time.Second, - returnCreateExec1: &dockertypes.IDResponse{ID: "12345678"}, - returnCreateExec2: nil, - returnStartExec: context.DeadlineExceeded, - returnInspectExec1: &dockertypes.ContainerExecInspect{ - ExecID: "200", - ContainerID: "12345678", - Running: true, - ExitCode: 0, - Pid: 100}, - returnInspectExec2: nil, - execProbeTimeout: true, - expectError: context.DeadlineExceeded, - }, { - description: "[ExecProbeTimeout=true] StartExec that takes longer than the probe timeout returns context.DeadlineExceeded", - timeout: 1 * time.Second, - returnCreateExec1: &dockertypes.IDResponse{ID: "12345678"}, - returnCreateExec2: nil, - startExecDelay: 5 * time.Second, - returnStartExec: fmt.Errorf("error in StartExec()"), - returnInspectExec1: nil, - returnInspectExec2: nil, - execProbeTimeout: true, - expectError: context.DeadlineExceeded, - }, { - description: "[ExecProbeTimeout=false] StartExec that takes longer than the probe timeout returns a error", - timeout: 1 * time.Second, - returnCreateExec1: &dockertypes.IDResponse{ID: "12345678"}, - returnCreateExec2: nil, - startExecDelay: 5 * time.Second, - returnStartExec: fmt.Errorf("error in StartExec()"), - returnInspectExec1: nil, - returnInspectExec2: nil, - execProbeTimeout: false, - expectError: fmt.Errorf("error in StartExec()"), - }} - - eh := &NativeExecHandler{} - // to avoid the default calling Finish(). More details in https://github.com/golang/mock/pull/422/ - ctrl := gomock.NewController(struct{ gomock.TestReporter }{t}) - container := getFakeContainerJSON() - cmd := []string{"/bin/bash"} - var stdin io.Reader - var stdout, stderr io.WriteCloser - var resize <-chan remotecommand.TerminalSize - - for _, tc := range testcases { - // these tests cannot be run in parallel due to the fact that they are feature gate dependent - tc := tc - t.Run(tc.description, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExecProbeTimeout, tc.execProbeTimeout)() - - mockClient := mockclient.NewMockInterface(ctrl) - mockClient.EXPECT().CreateExec(gomock.Any(), gomock.Any()).Return( - tc.returnCreateExec1, - tc.returnCreateExec2) - mockClient.EXPECT().StartExec(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, _ dockertypes.ExecStartCheck, _ libdocker.StreamOptions) { time.Sleep(tc.startExecDelay) }).Return(tc.returnStartExec) - mockClient.EXPECT().InspectExec(gomock.Any()).Return( - tc.returnInspectExec1, - tc.returnInspectExec2) - - // use parent context of 2 minutes since that's the default remote - // runtime connection timeout used by dockershim - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - err := eh.ExecInContainer(ctx, mockClient, container, cmd, stdin, stdout, stderr, false, resize, tc.timeout) - assert.Equal(t, tc.expectError, err) - }) - } -} - -func getFakeContainerJSON() *dockertypes.ContainerJSON { - return &dockertypes.ContainerJSON{ - ContainerJSONBase: &dockertypes.ContainerJSONBase{ - ID: "12345678", - Name: "fake_name", - Image: "fake_image", - State: &dockertypes.ContainerState{ - Running: false, - ExitCode: 0, - Pid: 100, - StartedAt: "2020-10-13T01:00:00-08:00", - FinishedAt: "2020-10-13T02:00:00-08:00", - }, - Created: "2020-10-13T01:00:00-08:00", - HostConfig: nil, - }, - Config: nil, - NetworkSettings: &dockertypes.NetworkSettings{}, - } -} diff --git a/pkg/kubelet/dockershim/helpers.go b/pkg/kubelet/dockershim/helpers.go deleted file mode 100644 index ca3db5e1818..00000000000 --- a/pkg/kubelet/dockershim/helpers.go +++ /dev/null @@ -1,442 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "errors" - "fmt" - "io" - "regexp" - "strconv" - "strings" - "sync/atomic" - - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - dockerfilters "github.com/docker/docker/api/types/filters" - dockernat "github.com/docker/go-connections/nat" - "k8s.io/klog/v2" - - v1 "k8s.io/api/core/v1" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/credentialprovider" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - "k8s.io/kubernetes/pkg/kubelet/types" - "k8s.io/kubernetes/pkg/util/parsers" -) - -const ( - annotationPrefix = "annotation." - securityOptSeparator = '=' -) - -var ( - conflictRE = regexp.MustCompile(`Conflict. (?:.)+ is already in use by container \"?([0-9a-z]+)\"?`) - - // this is hacky, but extremely common. - // if a container starts but the executable file is not found, runc gives a message that matches - startRE = regexp.MustCompile(`\\\\\\\"(.*)\\\\\\\": executable file not found`) - - defaultSeccompOpt = []dockerOpt{{"seccomp", v1.SeccompProfileNameUnconfined, ""}} -) - -// generateEnvList converts KeyValue list to a list of strings, in the form of -// '=', which can be understood by docker. -func generateEnvList(envs []*runtimeapi.KeyValue) (result []string) { - for _, env := range envs { - result = append(result, fmt.Sprintf("%s=%s", env.Key, env.Value)) - } - return -} - -// makeLabels converts annotations to labels and merge them with the given -// labels. This is necessary because docker does not support annotations; -// we *fake* annotations using labels. Note that docker labels are not -// updatable. -func makeLabels(labels, annotations map[string]string) map[string]string { - merged := make(map[string]string) - for k, v := range labels { - merged[k] = v - } - for k, v := range annotations { - // Assume there won't be conflict. - merged[fmt.Sprintf("%s%s", annotationPrefix, k)] = v - } - return merged -} - -// extractLabels converts raw docker labels to the CRI labels and annotations. -// It also filters out internal labels used by this shim. -func extractLabels(input map[string]string) (map[string]string, map[string]string) { - labels := make(map[string]string) - annotations := make(map[string]string) - for k, v := range input { - // Check if the key is used internally by the shim. - internal := false - for _, internalKey := range internalLabelKeys { - if k == internalKey { - internal = true - break - } - } - if internal { - continue - } - - // Delete the container name label for the sandbox. It is added in the shim, - // should not be exposed via CRI. - if k == types.KubernetesContainerNameLabel && - input[containerTypeLabelKey] == containerTypeLabelSandbox { - continue - } - - // Check if the label should be treated as an annotation. - if strings.HasPrefix(k, annotationPrefix) { - annotations[strings.TrimPrefix(k, annotationPrefix)] = v - continue - } - labels[k] = v - } - return labels, annotations -} - -// generateMountBindings converts the mount list to a list of strings that -// can be understood by docker. -// ':[:options]', where 'options' -// is a comma-separated list of the following strings: -// 'ro', if the path is read only -// 'Z', if the volume requires SELinux relabeling -// propagation mode such as 'rslave' -func generateMountBindings(mounts []*runtimeapi.Mount) []string { - result := make([]string, 0, len(mounts)) - for _, m := range mounts { - bind := fmt.Sprintf("%s:%s", m.HostPath, m.ContainerPath) - var attrs []string - if m.Readonly { - attrs = append(attrs, "ro") - } - // Only request relabeling if the pod provides an SELinux context. If the pod - // does not provide an SELinux context relabeling will label the volume with - // the container's randomly allocated MCS label. This would restrict access - // to the volume to the container which mounts it first. - if m.SelinuxRelabel { - attrs = append(attrs, "Z") - } - switch m.Propagation { - case runtimeapi.MountPropagation_PROPAGATION_PRIVATE: - // noop, private is default - case runtimeapi.MountPropagation_PROPAGATION_BIDIRECTIONAL: - attrs = append(attrs, "rshared") - case runtimeapi.MountPropagation_PROPAGATION_HOST_TO_CONTAINER: - attrs = append(attrs, "rslave") - default: - klog.InfoS("Unknown propagation mode for hostPath", "path", m.HostPath) - // Falls back to "private" - } - - if len(attrs) > 0 { - bind = fmt.Sprintf("%s:%s", bind, strings.Join(attrs, ",")) - } - result = append(result, bind) - } - return result -} - -func makePortsAndBindings(pm []*runtimeapi.PortMapping) (dockernat.PortSet, map[dockernat.Port][]dockernat.PortBinding) { - exposedPorts := dockernat.PortSet{} - portBindings := map[dockernat.Port][]dockernat.PortBinding{} - for _, port := range pm { - exteriorPort := port.HostPort - if exteriorPort == 0 { - // No need to do port binding when HostPort is not specified - continue - } - interiorPort := port.ContainerPort - // Some of this port stuff is under-documented voodoo. - // See http://stackoverflow.com/questions/20428302/binding-a-port-to-a-host-interface-using-the-rest-api - var protocol string - switch port.Protocol { - case runtimeapi.Protocol_UDP: - protocol = "/udp" - case runtimeapi.Protocol_TCP: - protocol = "/tcp" - case runtimeapi.Protocol_SCTP: - protocol = "/sctp" - default: - klog.InfoS("Unknown protocol, defaulting to TCP", "protocol", port.Protocol) - protocol = "/tcp" - } - - dockerPort := dockernat.Port(strconv.Itoa(int(interiorPort)) + protocol) - exposedPorts[dockerPort] = struct{}{} - - hostBinding := dockernat.PortBinding{ - HostPort: strconv.Itoa(int(exteriorPort)), - HostIP: port.HostIp, - } - - // Allow multiple host ports bind to same docker port - if existedBindings, ok := portBindings[dockerPort]; ok { - // If a docker port already map to a host port, just append the host ports - portBindings[dockerPort] = append(existedBindings, hostBinding) - } else { - // Otherwise, it's fresh new port binding - portBindings[dockerPort] = []dockernat.PortBinding{ - hostBinding, - } - } - } - return exposedPorts, portBindings -} - -// getApparmorSecurityOpts gets apparmor options from container config. -func getApparmorSecurityOpts(sc *runtimeapi.LinuxContainerSecurityContext, separator rune) ([]string, error) { - if sc == nil || sc.ApparmorProfile == "" { - return nil, nil - } - - appArmorOpts, err := getAppArmorOpts(sc.ApparmorProfile) - if err != nil { - return nil, err - } - - fmtOpts := fmtDockerOpts(appArmorOpts, separator) - return fmtOpts, nil -} - -// dockerFilter wraps around dockerfilters.Args and provides methods to modify -// the filter easily. -type dockerFilter struct { - args *dockerfilters.Args -} - -func newDockerFilter(args *dockerfilters.Args) *dockerFilter { - return &dockerFilter{args: args} -} - -func (f *dockerFilter) Add(key, value string) { - f.args.Add(key, value) -} - -func (f *dockerFilter) AddLabel(key, value string) { - f.Add("label", fmt.Sprintf("%s=%s", key, value)) -} - -// parseUserFromImageUser splits the user out of an user:group string. -func parseUserFromImageUser(id string) string { - if id == "" { - return id - } - // split instances where the id may contain user:group - if strings.Contains(id, ":") { - return strings.Split(id, ":")[0] - } - // no group, just return the id - return id -} - -// getUserFromImageUser gets uid or user name of the image user. -// If user is numeric, it will be treated as uid; or else, it is treated as user name. -func getUserFromImageUser(imageUser string) (*int64, string) { - user := parseUserFromImageUser(imageUser) - // return both nil if user is not specified in the image. - if user == "" { - return nil, "" - } - // user could be either uid or user name. Try to interpret as numeric uid. - uid, err := strconv.ParseInt(user, 10, 64) - if err != nil { - // If user is non numeric, assume it's user name. - return nil, user - } - // If user is a numeric uid. - return &uid, "" -} - -// See #33189. If the previous attempt to create a sandbox container name FOO -// failed due to "device or resource busy", it is possible that docker did -// not clean up properly and has inconsistent internal state. Docker would -// not report the existence of FOO, but would complain if user wants to -// create a new container named FOO. To work around this, we parse the error -// message to identify failure caused by naming conflict, and try to remove -// the old container FOO. -// See #40443. Sometimes even removal may fail with "no such container" error. -// In that case we have to create the container with a randomized name. -// TODO(random-liu): Remove this work around after docker 1.11 is deprecated. -// TODO(#33189): Monitor the tests to see if the fix is sufficient. -func recoverFromCreationConflictIfNeeded(client libdocker.Interface, createConfig dockertypes.ContainerCreateConfig, err error) (*dockercontainer.ContainerCreateCreatedBody, error) { - matches := conflictRE.FindStringSubmatch(err.Error()) - if len(matches) != 2 { - return nil, err - } - - id := matches[1] - klog.InfoS("Unable to create pod sandbox due to conflict. Attempting to remove sandbox", "containerID", id) - rmErr := client.RemoveContainer(id, dockertypes.ContainerRemoveOptions{RemoveVolumes: true}) - if rmErr == nil { - klog.V(2).InfoS("Successfully removed conflicting container", "containerID", id) - return nil, err - } - klog.ErrorS(rmErr, "Failed to remove the conflicting container", "containerID", id) - // Return if the error is not container not found error. - if !libdocker.IsContainerNotFoundError(rmErr) { - return nil, err - } - - // randomize the name to avoid conflict. - createConfig.Name = randomizeName(createConfig.Name) - klog.V(2).InfoS("Create the container with the randomized name", "containerName", createConfig.Name) - return client.CreateContainer(createConfig) -} - -// transformStartContainerError does regex parsing on returned error -// for where container runtimes are giving less than ideal error messages. -func transformStartContainerError(err error) error { - if err == nil { - return nil - } - matches := startRE.FindStringSubmatch(err.Error()) - if len(matches) > 0 { - return fmt.Errorf("executable not found in $PATH") - } - return err -} - -// ensureSandboxImageExists pulls the sandbox image when it's not present. -func ensureSandboxImageExists(client libdocker.Interface, image string) error { - _, err := client.InspectImageByRef(image) - if err == nil { - return nil - } - if !libdocker.IsImageNotFoundError(err) { - return fmt.Errorf("failed to inspect sandbox image %q: %v", image, err) - } - - repoToPull, _, _, err := parsers.ParseImageName(image) - if err != nil { - return err - } - - keyring := credentialprovider.NewDockerKeyring() - creds, withCredentials := keyring.Lookup(repoToPull) - if !withCredentials { - klog.V(3).InfoS("Pulling the image without credentials", "image", image) - - err := client.PullImage(image, dockertypes.AuthConfig{}, dockertypes.ImagePullOptions{}) - if err != nil { - return fmt.Errorf("failed pulling image %q: %v", image, err) - } - - return nil - } - - var pullErrs []error - for _, currentCreds := range creds { - authConfig := dockertypes.AuthConfig(currentCreds) - err := client.PullImage(image, authConfig, dockertypes.ImagePullOptions{}) - // If there was no error, return success - if err == nil { - return nil - } - - pullErrs = append(pullErrs, err) - } - - return utilerrors.NewAggregate(pullErrs) -} - -func getAppArmorOpts(profile string) ([]dockerOpt, error) { - if profile == "" || profile == v1.AppArmorBetaProfileRuntimeDefault { - // The docker applies the default profile by default. - return nil, nil - } - - // Return unconfined profile explicitly - if profile == v1.AppArmorBetaProfileNameUnconfined { - return []dockerOpt{{"apparmor", v1.AppArmorBetaProfileNameUnconfined, ""}}, nil - } - - // Assume validation has already happened. - profileName := strings.TrimPrefix(profile, v1.AppArmorBetaProfileNamePrefix) - return []dockerOpt{{"apparmor", profileName, ""}}, nil -} - -// fmtDockerOpts formats the docker security options using the given separator. -func fmtDockerOpts(opts []dockerOpt, sep rune) []string { - fmtOpts := make([]string, len(opts)) - for i, opt := range opts { - fmtOpts[i] = fmt.Sprintf("%s%c%s", opt.key, sep, opt.value) - } - return fmtOpts -} - -type dockerOpt struct { - // The key-value pair passed to docker. - key, value string - // The alternative value to use in log/event messages. - msg string -} - -// Expose key/value from dockerOpt. -func (d dockerOpt) GetKV() (string, string) { - return d.key, d.value -} - -// sharedWriteLimiter limits the total output written across one or more streams. -type sharedWriteLimiter struct { - delegate io.Writer - limit *int64 -} - -func (w sharedWriteLimiter) Write(p []byte) (int, error) { - if len(p) == 0 { - return 0, nil - } - limit := atomic.LoadInt64(w.limit) - if limit <= 0 { - return 0, errMaximumWrite - } - var truncated bool - if limit < int64(len(p)) { - p = p[0:limit] - truncated = true - } - n, err := w.delegate.Write(p) - if n > 0 { - atomic.AddInt64(w.limit, -1*int64(n)) - } - if err == nil && truncated { - err = errMaximumWrite - } - return n, err -} - -func sharedLimitWriter(w io.Writer, limit *int64) io.Writer { - if w == nil { - return nil - } - return &sharedWriteLimiter{ - delegate: w, - limit: limit, - } -} - -var errMaximumWrite = errors.New("maximum write") diff --git a/pkg/kubelet/dockershim/helpers_linux.go b/pkg/kubelet/dockershim/helpers_linux.go deleted file mode 100644 index 154c503a1ca..00000000000 --- a/pkg/kubelet/dockershim/helpers_linux.go +++ /dev/null @@ -1,158 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "bytes" - "crypto/md5" - "encoding/json" - "fmt" - "io/ioutil" - "path/filepath" - "strings" - - "github.com/blang/semver" - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - v1 "k8s.io/api/core/v1" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// DefaultMemorySwap always returns 0 for no memory swap in a sandbox -func DefaultMemorySwap() int64 { - return 0 -} - -func (ds *dockerService) getSecurityOpts(seccompProfile string, separator rune) ([]string, error) { - // Apply seccomp options. - seccompSecurityOpts, err := getSeccompSecurityOpts(seccompProfile, separator) - if err != nil { - return nil, fmt.Errorf("failed to generate seccomp security options for container: %v", err) - } - - return seccompSecurityOpts, nil -} - -func (ds *dockerService) getSandBoxSecurityOpts(separator rune) []string { - // run sandbox with no-new-privileges and using runtime/default - // sending no "seccomp=" means docker will use default profile - return []string{"no-new-privileges"} -} - -func getSeccompDockerOpts(seccompProfile string) ([]dockerOpt, error) { - if seccompProfile == "" || seccompProfile == v1.SeccompProfileNameUnconfined { - // return early the default - return defaultSeccompOpt, nil - } - - if seccompProfile == v1.SeccompProfileRuntimeDefault || seccompProfile == v1.DeprecatedSeccompProfileDockerDefault { - // return nil so docker will load the default seccomp profile - return nil, nil - } - - if !strings.HasPrefix(seccompProfile, v1.SeccompLocalhostProfileNamePrefix) { - return nil, fmt.Errorf("unknown seccomp profile option: %s", seccompProfile) - } - - // get the full path of seccomp profile when prefixed with 'localhost/'. - fname := strings.TrimPrefix(seccompProfile, v1.SeccompLocalhostProfileNamePrefix) - if !filepath.IsAbs(fname) { - return nil, fmt.Errorf("seccomp profile path must be absolute, but got relative path %q", fname) - } - file, err := ioutil.ReadFile(filepath.FromSlash(fname)) - if err != nil { - return nil, fmt.Errorf("cannot load seccomp profile %q: %v", fname, err) - } - - b := bytes.NewBuffer(nil) - if err := json.Compact(b, file); err != nil { - return nil, err - } - // Rather than the full profile, just put the filename & md5sum in the event log. - msg := fmt.Sprintf("%s(md5:%x)", fname, md5.Sum(file)) - - return []dockerOpt{{"seccomp", b.String(), msg}}, nil -} - -// getSeccompSecurityOpts gets container seccomp options from container seccomp profile. -// It is an experimental feature and may be promoted to official runtime api in the future. -func getSeccompSecurityOpts(seccompProfile string, separator rune) ([]string, error) { - seccompOpts, err := getSeccompDockerOpts(seccompProfile) - if err != nil { - return nil, err - } - return fmtDockerOpts(seccompOpts, separator), nil -} - -func (ds *dockerService) updateCreateConfig( - createConfig *dockertypes.ContainerCreateConfig, - config *runtimeapi.ContainerConfig, - sandboxConfig *runtimeapi.PodSandboxConfig, - podSandboxID string, securityOptSep rune, apiVersion *semver.Version) error { - // Apply Linux-specific options if applicable. - if lc := config.GetLinux(); lc != nil { - // TODO: Check if the units are correct. - // TODO: Can we assume the defaults are sane? - rOpts := lc.GetResources() - if rOpts != nil { - createConfig.HostConfig.Resources = dockercontainer.Resources{ - // Memory and MemorySwap are set to the same value, this prevents containers from using any swap. - Memory: rOpts.MemoryLimitInBytes, - MemorySwap: rOpts.MemoryLimitInBytes, - CPUShares: rOpts.CpuShares, - CPUQuota: rOpts.CpuQuota, - CPUPeriod: rOpts.CpuPeriod, - CpusetCpus: rOpts.CpusetCpus, - CpusetMems: rOpts.CpusetMems, - } - createConfig.HostConfig.OomScoreAdj = int(rOpts.OomScoreAdj) - } - // Note: ShmSize is handled in kube_docker_client.go - - // Apply security context. - if err := applyContainerSecurityContext(lc, podSandboxID, createConfig.Config, createConfig.HostConfig, securityOptSep); err != nil { - return fmt.Errorf("failed to apply container security context for container %q: %v", config.Metadata.Name, err) - } - } - - // Apply cgroupsParent derived from the sandbox config. - if lc := sandboxConfig.GetLinux(); lc != nil { - // Apply Cgroup options. - cgroupParent, err := ds.GenerateExpectedCgroupParent(lc.CgroupParent) - if err != nil { - return fmt.Errorf("failed to generate cgroup parent in expected syntax for container %q: %v", config.Metadata.Name, err) - } - createConfig.HostConfig.CgroupParent = cgroupParent - } - - return nil -} - -func (ds *dockerService) determinePodIPBySandboxID(uid string) []string { - return nil -} - -func getNetworkNamespace(c *dockertypes.ContainerJSON) (string, error) { - if c.State.Pid == 0 { - // Docker reports pid 0 for an exited container. - return "", fmt.Errorf("cannot find network namespace for the terminated container %q", c.ID) - } - return fmt.Sprintf(dockerNetNSFmt, c.State.Pid), nil -} diff --git a/pkg/kubelet/dockershim/helpers_linux_test.go b/pkg/kubelet/dockershim/helpers_linux_test.go deleted file mode 100644 index ada9f565ee6..00000000000 --- a/pkg/kubelet/dockershim/helpers_linux_test.go +++ /dev/null @@ -1,109 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "k8s.io/api/core/v1" -) - -func TestGetSeccompSecurityOpts(t *testing.T) { - tests := []struct { - msg string - seccompProfile string - expectedOpts []string - }{{ - msg: "No security annotations", - seccompProfile: "", - expectedOpts: []string{"seccomp=unconfined"}, - }, { - msg: "Seccomp unconfined", - seccompProfile: "unconfined", - expectedOpts: []string{"seccomp=unconfined"}, - }, { - msg: "Seccomp default", - seccompProfile: v1.SeccompProfileRuntimeDefault, - expectedOpts: nil, - }, { - msg: "Seccomp deprecated default", - seccompProfile: v1.DeprecatedSeccompProfileDockerDefault, - expectedOpts: nil, - }} - - for i, test := range tests { - opts, err := getSeccompSecurityOpts(test.seccompProfile, '=') - assert.NoError(t, err, "TestCase[%d]: %s", i, test.msg) - assert.Len(t, opts, len(test.expectedOpts), "TestCase[%d]: %s", i, test.msg) - for _, opt := range test.expectedOpts { - assert.Contains(t, opts, opt, "TestCase[%d]: %s", i, test.msg) - } - } -} - -func TestLoadSeccompLocalhostProfiles(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "seccomp-local-profile-test") - require.NoError(t, err) - defer os.RemoveAll(tmpdir) - testProfile := `{"foo": "bar"}` - err = ioutil.WriteFile(filepath.Join(tmpdir, "test"), []byte(testProfile), 0644) - require.NoError(t, err) - - tests := []struct { - msg string - seccompProfile string - expectedOpts []string - expectErr bool - }{{ - msg: "Seccomp localhost/test profile should return correct seccomp profiles", - seccompProfile: "localhost/" + filepath.Join(tmpdir, "test"), - expectedOpts: []string{`seccomp={"foo":"bar"}`}, - expectErr: false, - }, { - msg: "Non-existent profile should return error", - seccompProfile: "localhost/" + filepath.Join(tmpdir, "fixtures/non-existent"), - expectedOpts: nil, - expectErr: true, - }, { - msg: "Relative profile path should return error", - seccompProfile: "localhost/fixtures/test", - expectedOpts: nil, - expectErr: true, - }} - - for i, test := range tests { - opts, err := getSeccompSecurityOpts(test.seccompProfile, '=') - if test.expectErr { - assert.Error(t, err, fmt.Sprintf("TestCase[%d]: %s", i, test.msg)) - continue - } - assert.NoError(t, err, "TestCase[%d]: %s", i, test.msg) - assert.Len(t, opts, len(test.expectedOpts), "TestCase[%d]: %s", i, test.msg) - for _, opt := range test.expectedOpts { - assert.Contains(t, opts, opt, "TestCase[%d]: %s", i, test.msg) - } - } -} diff --git a/pkg/kubelet/dockershim/helpers_test.go b/pkg/kubelet/dockershim/helpers_test.go deleted file mode 100644 index b70b447f705..00000000000 --- a/pkg/kubelet/dockershim/helpers_test.go +++ /dev/null @@ -1,441 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "bytes" - "errors" - "fmt" - "sync" - "testing" - - dockertypes "github.com/docker/docker/api/types" - dockernat "github.com/docker/go-connections/nat" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - v1 "k8s.io/api/core/v1" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" -) - -func TestLabelsAndAnnotationsRoundTrip(t *testing.T) { - expectedLabels := map[string]string{"foo.123.abc": "baz", "bar.456.xyz": "qwe"} - expectedAnnotations := map[string]string{"uio.ert": "dfs", "jkl": "asd"} - // Merge labels and annotations into docker labels. - dockerLabels := makeLabels(expectedLabels, expectedAnnotations) - // Extract labels and annotations from docker labels. - actualLabels, actualAnnotations := extractLabels(dockerLabels) - assert.Equal(t, expectedLabels, actualLabels) - assert.Equal(t, expectedAnnotations, actualAnnotations) -} - -// TestGetApparmorSecurityOpts tests the logic of generating container apparmor options from sandbox annotations. -func TestGetApparmorSecurityOpts(t *testing.T) { - makeConfig := func(profile string) *runtimeapi.LinuxContainerSecurityContext { - return &runtimeapi.LinuxContainerSecurityContext{ - ApparmorProfile: profile, - } - } - - tests := []struct { - msg string - config *runtimeapi.LinuxContainerSecurityContext - expectedOpts []string - }{{ - msg: "No AppArmor options", - config: makeConfig(""), - expectedOpts: nil, - }, { - msg: "AppArmor runtime/default", - config: makeConfig("runtime/default"), - expectedOpts: []string{}, - }, { - msg: "AppArmor local profile", - config: makeConfig(v1.AppArmorBetaProfileNamePrefix + "foo"), - expectedOpts: []string{"apparmor=foo"}, - }} - - for i, test := range tests { - opts, err := getApparmorSecurityOpts(test.config, '=') - assert.NoError(t, err, "TestCase[%d]: %s", i, test.msg) - assert.Len(t, opts, len(test.expectedOpts), "TestCase[%d]: %s", i, test.msg) - for _, opt := range test.expectedOpts { - assert.Contains(t, opts, opt, "TestCase[%d]: %s", i, test.msg) - } - } -} - -// TestGetUserFromImageUser tests the logic of getting image uid or user name of image user. -func TestGetUserFromImageUser(t *testing.T) { - newI64 := func(i int64) *int64 { return &i } - for c, test := range map[string]struct { - user string - uid *int64 - name string - }{ - "no gid": { - user: "0", - uid: newI64(0), - }, - "uid/gid": { - user: "0:1", - uid: newI64(0), - }, - "empty user": { - user: "", - }, - "multiple spearators": { - user: "1:2:3", - uid: newI64(1), - }, - "root username": { - user: "root:root", - name: "root", - }, - "username": { - user: "test:test", - name: "test", - }, - } { - t.Logf("TestCase - %q", c) - actualUID, actualName := getUserFromImageUser(test.user) - assert.Equal(t, test.uid, actualUID) - assert.Equal(t, test.name, actualName) - } -} - -func TestParsingCreationConflictError(t *testing.T) { - // Expected error message from docker. - msgs := []string{ - "Conflict. The name \"/k8s_POD_pfpod_e2e-tests-port-forwarding-dlxt2_81a3469e-99e1-11e6-89f2-42010af00002_0\" is already in use by container 24666ab8c814d16f986449e504ea0159468ddf8da01897144a770f66dce0e14e. You have to remove (or rename) that container to be able to reuse that name.", - "Conflict. The name \"/k8s_POD_pfpod_e2e-tests-port-forwarding-dlxt2_81a3469e-99e1-11e6-89f2-42010af00002_0\" is already in use by container \"24666ab8c814d16f986449e504ea0159468ddf8da01897144a770f66dce0e14e\". You have to remove (or rename) that container to be able to reuse that name.", - } - - for _, msg := range msgs { - matches := conflictRE.FindStringSubmatch(msg) - require.Len(t, matches, 2) - require.Equal(t, matches[1], "24666ab8c814d16f986449e504ea0159468ddf8da01897144a770f66dce0e14e") - } -} - -func TestEnsureSandboxImageExists(t *testing.T) { - sandboxImage := "gcr.io/test/image" - authConfig := dockertypes.AuthConfig{Username: "user", Password: "pass"} - for desc, test := range map[string]struct { - injectImage bool - imgNeedsAuth bool - injectErr error - calls []string - err bool - configJSON string - }{ - "should not pull image when it already exists": { - injectImage: true, - injectErr: nil, - calls: []string{"inspect_image"}, - }, - "should pull image when it doesn't exist": { - injectImage: false, - injectErr: libdocker.ImageNotFoundError{ID: "image_id"}, - calls: []string{"inspect_image", "pull"}, - }, - "should return error when inspect image fails": { - injectImage: false, - injectErr: fmt.Errorf("arbitrary error"), - calls: []string{"inspect_image"}, - err: true, - }, - "should return error when image pull needs private auth, but none provided": { - injectImage: true, - imgNeedsAuth: true, - injectErr: libdocker.ImageNotFoundError{ID: "image_id"}, - calls: []string{"inspect_image", "pull"}, - err: true, - }, - } { - t.Logf("TestCase: %q", desc) - _, fakeDocker, _ := newTestDockerService() - if test.injectImage { - images := []dockertypes.ImageSummary{{ID: sandboxImage}} - fakeDocker.InjectImages(images) - if test.imgNeedsAuth { - fakeDocker.MakeImagesPrivate(images, authConfig) - } - } - fakeDocker.InjectError("inspect_image", test.injectErr) - - err := ensureSandboxImageExists(fakeDocker, sandboxImage) - assert.NoError(t, fakeDocker.AssertCalls(test.calls)) - assert.Equal(t, test.err, err != nil) - } -} - -func TestMakePortsAndBindings(t *testing.T) { - for desc, test := range map[string]struct { - pm []*runtimeapi.PortMapping - exposedPorts dockernat.PortSet - portmappings map[dockernat.Port][]dockernat.PortBinding - }{ - "no port mapping": { - pm: nil, - exposedPorts: map[dockernat.Port]struct{}{}, - portmappings: map[dockernat.Port][]dockernat.PortBinding{}, - }, - "tcp port mapping": { - pm: []*runtimeapi.PortMapping{ - { - Protocol: runtimeapi.Protocol_TCP, - ContainerPort: 80, - HostPort: 80, - }, - }, - exposedPorts: map[dockernat.Port]struct{}{ - "80/tcp": {}, - }, - portmappings: map[dockernat.Port][]dockernat.PortBinding{ - "80/tcp": { - { - HostPort: "80", - }, - }, - }, - }, - "udp port mapping": { - pm: []*runtimeapi.PortMapping{ - { - Protocol: runtimeapi.Protocol_UDP, - ContainerPort: 80, - HostPort: 80, - }, - }, - exposedPorts: map[dockernat.Port]struct{}{ - "80/udp": {}, - }, - portmappings: map[dockernat.Port][]dockernat.PortBinding{ - "80/udp": { - { - HostPort: "80", - }, - }, - }, - }, - "multiple port mappings": { - pm: []*runtimeapi.PortMapping{ - { - Protocol: runtimeapi.Protocol_TCP, - ContainerPort: 80, - HostPort: 80, - }, - { - Protocol: runtimeapi.Protocol_TCP, - ContainerPort: 80, - HostPort: 81, - }, - }, - exposedPorts: map[dockernat.Port]struct{}{ - "80/tcp": {}, - }, - portmappings: map[dockernat.Port][]dockernat.PortBinding{ - "80/tcp": { - { - HostPort: "80", - }, - { - HostPort: "81", - }, - }, - }, - }, - } { - t.Logf("TestCase: %s", desc) - actualExposedPorts, actualPortMappings := makePortsAndBindings(test.pm) - assert.Equal(t, test.exposedPorts, actualExposedPorts) - assert.Equal(t, test.portmappings, actualPortMappings) - } -} - -func TestGenerateMountBindings(t *testing.T) { - mounts := []*runtimeapi.Mount{ - // everything default - { - HostPath: "/mnt/1", - ContainerPath: "/var/lib/mysql/1", - }, - // readOnly - { - HostPath: "/mnt/2", - ContainerPath: "/var/lib/mysql/2", - Readonly: true, - }, - // SELinux - { - HostPath: "/mnt/3", - ContainerPath: "/var/lib/mysql/3", - SelinuxRelabel: true, - }, - // Propagation private - { - HostPath: "/mnt/4", - ContainerPath: "/var/lib/mysql/4", - Propagation: runtimeapi.MountPropagation_PROPAGATION_PRIVATE, - }, - // Propagation rslave - { - HostPath: "/mnt/5", - ContainerPath: "/var/lib/mysql/5", - Propagation: runtimeapi.MountPropagation_PROPAGATION_HOST_TO_CONTAINER, - }, - // Propagation rshared - { - HostPath: "/mnt/6", - ContainerPath: "/var/lib/mysql/6", - Propagation: runtimeapi.MountPropagation_PROPAGATION_BIDIRECTIONAL, - }, - // Propagation unknown (falls back to private) - { - HostPath: "/mnt/7", - ContainerPath: "/var/lib/mysql/7", - Propagation: runtimeapi.MountPropagation(42), - }, - // Everything - { - HostPath: "/mnt/8", - ContainerPath: "/var/lib/mysql/8", - Readonly: true, - SelinuxRelabel: true, - Propagation: runtimeapi.MountPropagation_PROPAGATION_BIDIRECTIONAL, - }, - } - expectedResult := []string{ - "/mnt/1:/var/lib/mysql/1", - "/mnt/2:/var/lib/mysql/2:ro", - "/mnt/3:/var/lib/mysql/3:Z", - "/mnt/4:/var/lib/mysql/4", - "/mnt/5:/var/lib/mysql/5:rslave", - "/mnt/6:/var/lib/mysql/6:rshared", - "/mnt/7:/var/lib/mysql/7", - "/mnt/8:/var/lib/mysql/8:ro,Z,rshared", - } - result := generateMountBindings(mounts) - - assert.Equal(t, expectedResult, result) -} - -func TestLimitedWriter(t *testing.T) { - max := func(x, y int64) int64 { - if x > y { - return x - } - return y - } - for name, tc := range map[string]struct { - w bytes.Buffer - toWrite string - limit int64 - wants string - wantsErr error - }{ - "nil": {}, - "neg": { - toWrite: "a", - wantsErr: errMaximumWrite, - limit: -1, - }, - "1byte-over": { - toWrite: "a", - wantsErr: errMaximumWrite, - }, - "1byte-maxed": { - toWrite: "a", - wants: "a", - limit: 1, - }, - "1byte-under": { - toWrite: "a", - wants: "a", - limit: 2, - }, - "6byte-over": { - toWrite: "foobar", - wants: "foo", - limit: 3, - wantsErr: errMaximumWrite, - }, - "6byte-maxed": { - toWrite: "foobar", - wants: "foobar", - limit: 6, - }, - "6byte-under": { - toWrite: "foobar", - wants: "foobar", - limit: 20, - }, - } { - t.Run(name, func(t *testing.T) { - limit := tc.limit - w := sharedLimitWriter(&tc.w, &limit) - n, err := w.Write([]byte(tc.toWrite)) - if int64(n) > max(0, tc.limit) { - t.Fatalf("bytes written (%d) exceeds limit (%d)", n, tc.limit) - } - if (err != nil) != (tc.wantsErr != nil) { - if err != nil { - t.Fatal("unexpected error:", err) - } - t.Fatal("expected error:", err) - } - if err != nil { - if !errors.Is(err, tc.wantsErr) { - t.Fatal("expected error: ", tc.wantsErr, " instead of: ", err) - } - if !errors.Is(err, errMaximumWrite) { - return - } - // check contents for errMaximumWrite - } - if s := tc.w.String(); s != tc.wants { - t.Fatalf("expected %q instead of %q", tc.wants, s) - } - }) - } - - // test concurrency. run this test a bunch of times to attempt to flush - // out any data races or concurrency issues. - for i := 0; i < 1000; i++ { - var ( - b1, b2 bytes.Buffer - limit = int64(10) - w1 = sharedLimitWriter(&b1, &limit) - w2 = sharedLimitWriter(&b2, &limit) - ch = make(chan struct{}) - wg sync.WaitGroup - ) - wg.Add(2) - go func() { defer wg.Done(); <-ch; w1.Write([]byte("hello")) }() - go func() { defer wg.Done(); <-ch; w2.Write([]byte("world")) }() - close(ch) - wg.Wait() - if limit != 0 { - t.Fatalf("expected max limit to be reached, instead of %d", limit) - } - } -} diff --git a/pkg/kubelet/dockershim/helpers_unsupported.go b/pkg/kubelet/dockershim/helpers_unsupported.go deleted file mode 100644 index 3c655c5551f..00000000000 --- a/pkg/kubelet/dockershim/helpers_unsupported.go +++ /dev/null @@ -1,62 +0,0 @@ -//go:build !linux && !windows && !dockerless -// +build !linux,!windows,!dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - - "github.com/blang/semver" - dockertypes "github.com/docker/docker/api/types" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/klog/v2" -) - -// DefaultMemorySwap always returns -1 for no memory swap in a sandbox -func DefaultMemorySwap() int64 { - return -1 -} - -func (ds *dockerService) getSecurityOpts(seccompProfile string, separator rune) ([]string, error) { - klog.InfoS("getSecurityOpts is unsupported in this build") - return nil, nil -} - -func (ds *dockerService) getSandBoxSecurityOpts(separator rune) []string { - klog.InfoS("getSandBoxSecurityOpts is unsupported in this build") - return nil -} - -func (ds *dockerService) updateCreateConfig( - createConfig *dockertypes.ContainerCreateConfig, - config *runtimeapi.ContainerConfig, - sandboxConfig *runtimeapi.PodSandboxConfig, - podSandboxID string, securityOptSep rune, apiVersion *semver.Version) error { - klog.InfoS("updateCreateConfig is unsupported in this build") - return nil -} - -func (ds *dockerService) determinePodIPBySandboxID(uid string) []string { - klog.InfoS("determinePodIPBySandboxID is unsupported in this build") - return nil -} - -func getNetworkNamespace(c *dockertypes.ContainerJSON) (string, error) { - return "", fmt.Errorf("unsupported platform") -} diff --git a/pkg/kubelet/dockershim/helpers_windows.go b/pkg/kubelet/dockershim/helpers_windows.go deleted file mode 100644 index 1fd8155bec4..00000000000 --- a/pkg/kubelet/dockershim/helpers_windows.go +++ /dev/null @@ -1,161 +0,0 @@ -//go:build windows && !dockerless -// +build windows,!dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "os" - "runtime" - - "github.com/blang/semver" - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - dockerfilters "github.com/docker/docker/api/types/filters" - "k8s.io/klog/v2" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// DefaultMemorySwap always returns 0 for no memory swap in a sandbox -func DefaultMemorySwap() int64 { - return 0 -} - -func (ds *dockerService) getSecurityOpts(seccompProfile string, separator rune) ([]string, error) { - if seccompProfile != "" { - klog.InfoS("seccomp annotations are not supported on windows") - } - return nil, nil -} - -func (ds *dockerService) getSandBoxSecurityOpts(separator rune) []string { - // Currently, Windows container does not support privileged mode, so no no-new-privileges flag can be returned directly like Linux - // If the future Windows container has new support for privileged mode, we can adjust it here - return nil -} - -func (ds *dockerService) updateCreateConfig( - createConfig *dockertypes.ContainerCreateConfig, - config *runtimeapi.ContainerConfig, - sandboxConfig *runtimeapi.PodSandboxConfig, - podSandboxID string, securityOptSep rune, apiVersion *semver.Version) error { - if networkMode := os.Getenv("CONTAINER_NETWORK"); networkMode != "" { - createConfig.HostConfig.NetworkMode = dockercontainer.NetworkMode(networkMode) - } else { - // Todo: Refactor this call in future for calling methods directly in security_context.go - modifyHostOptionsForContainer(nil, podSandboxID, createConfig.HostConfig) - } - - // Apply Windows-specific options if applicable. - if wc := config.GetWindows(); wc != nil { - rOpts := wc.GetResources() - if rOpts != nil { - // Precedence and units for these are described at length in kuberuntime_container_windows.go - generateWindowsContainerConfig() - createConfig.HostConfig.Resources = dockercontainer.Resources{ - Memory: rOpts.MemoryLimitInBytes, - CPUShares: rOpts.CpuShares, - CPUCount: rOpts.CpuCount, - NanoCPUs: rOpts.CpuMaximum * int64(runtime.NumCPU()) * (1e9 / 10000), - } - } - - // Apply security context. - applyWindowsContainerSecurityContext(wc.GetSecurityContext(), createConfig.Config, createConfig.HostConfig) - } - - return nil -} - -// applyWindowsContainerSecurityContext updates docker container options according to security context. -func applyWindowsContainerSecurityContext(wsc *runtimeapi.WindowsContainerSecurityContext, config *dockercontainer.Config, hc *dockercontainer.HostConfig) { - if wsc == nil { - return - } - - if wsc.GetRunAsUsername() != "" { - config.User = wsc.GetRunAsUsername() - } -} - -func (ds *dockerService) determinePodIPBySandboxID(sandboxID string) []string { - opts := dockertypes.ContainerListOptions{ - All: true, - Filters: dockerfilters.NewArgs(), - } - - f := newDockerFilter(&opts.Filters) - f.AddLabel(containerTypeLabelKey, containerTypeLabelContainer) - f.AddLabel(sandboxIDLabelKey, sandboxID) - containers, err := ds.client.ListContainers(opts) - if err != nil { - return nil - } - - for _, c := range containers { - r, err := ds.client.InspectContainer(c.ID) - if err != nil { - continue - } - - // Versions and feature support - // ============================ - // Windows version == Windows Server, Version 1709, Supports both sandbox and non-sandbox case - // Windows version == Windows Server 2016 Support only non-sandbox case - // Windows version < Windows Server 2016 is Not Supported - - // Sandbox support in Windows mandates CNI Plugin. - // Presence of CONTAINER_NETWORK flag is considered as non-Sandbox cases here - - // Todo: Add a kernel version check for more validation - - if networkMode := os.Getenv("CONTAINER_NETWORK"); networkMode == "" { - // On Windows, every container that is created in a Sandbox, needs to invoke CNI plugin again for adding the Network, - // with the shared container name as NetNS info, - // This is passed down to the platform to replicate some necessary information to the new container - - // - // This place is chosen as a hack for now, since ds.getIP would end up calling CNI's addToNetwork - // That is why addToNetwork is required to be idempotent - - // Instead of relying on this call, an explicit call to addToNetwork should be - // done immediately after ContainerCreation, in case of Windows only. TBD Issue # to handle this - - // Do not return any IP, so that we would continue and get the IP of the Sandbox. - // Windows 1709 and 1803 doesn't have the Namespace support, so getIP() is called - // to replicate the DNS registry key to the Workload container (IP/Gateway/MAC is - // set separately than DNS). - // TODO(feiskyer): remove this workaround after Namespace is supported in Windows RS5. - ds.getIPs(sandboxID, r) - } else { - // ds.getIP will call the CNI plugin to fetch the IP - if containerIPs := ds.getIPs(c.ID, r); len(containerIPs) != 0 { - return containerIPs - } - } - } - - return nil -} - -func getNetworkNamespace(c *dockertypes.ContainerJSON) (string, error) { - // Currently in windows there is no identifier exposed for network namespace - // Like docker, the referenced container id is used to figure out the network namespace id internally by the platform - // so returning the docker networkMode (which holds container: for network namespace here - return string(c.HostConfig.NetworkMode), nil -} diff --git a/pkg/kubelet/dockershim/libdocker/client.go b/pkg/kubelet/dockershim/libdocker/client.go deleted file mode 100644 index a1f3feb44ce..00000000000 --- a/pkg/kubelet/dockershim/libdocker/client.go +++ /dev/null @@ -1,101 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes 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. -*/ - -//go:generate mockgen -copyright_file=$BUILD_TAG_FILE -source=client.go -destination=testing/mock_client.go -package=testing Interface -package libdocker - -import ( - "os" - "time" - - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - dockerimagetypes "github.com/docker/docker/api/types/image" - dockerapi "github.com/docker/docker/client" - "k8s.io/klog/v2" -) - -const ( - // https://docs.docker.com/engine/reference/api/docker_remote_api/ - // docker version should be at least 1.13.1 - MinimumDockerAPIVersion = "1.26.0" - - // Status of a container returned by ListContainers. - StatusRunningPrefix = "Up" - StatusCreatedPrefix = "Created" - StatusExitedPrefix = "Exited" - - // Fake docker endpoint - FakeDockerEndpoint = "fake://" -) - -// Interface is an abstract interface for testability. It abstracts the interface of docker client. -type Interface interface { - ListContainers(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error) - InspectContainer(id string) (*dockertypes.ContainerJSON, error) - InspectContainerWithSize(id string) (*dockertypes.ContainerJSON, error) - CreateContainer(dockertypes.ContainerCreateConfig) (*dockercontainer.ContainerCreateCreatedBody, error) - StartContainer(id string) error - StopContainer(id string, timeout time.Duration) error - UpdateContainerResources(id string, updateConfig dockercontainer.UpdateConfig) error - RemoveContainer(id string, opts dockertypes.ContainerRemoveOptions) error - InspectImageByRef(imageRef string) (*dockertypes.ImageInspect, error) - InspectImageByID(imageID string) (*dockertypes.ImageInspect, error) - ListImages(opts dockertypes.ImageListOptions) ([]dockertypes.ImageSummary, error) - PullImage(image string, auth dockertypes.AuthConfig, opts dockertypes.ImagePullOptions) error - RemoveImage(image string, opts dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDeleteResponseItem, error) - ImageHistory(id string) ([]dockerimagetypes.HistoryResponseItem, error) - Logs(string, dockertypes.ContainerLogsOptions, StreamOptions) error - Version() (*dockertypes.Version, error) - Info() (*dockertypes.Info, error) - CreateExec(string, dockertypes.ExecConfig) (*dockertypes.IDResponse, error) - StartExec(string, dockertypes.ExecStartCheck, StreamOptions) error - InspectExec(id string) (*dockertypes.ContainerExecInspect, error) - AttachToContainer(string, dockertypes.ContainerAttachOptions, StreamOptions) error - ResizeContainerTTY(id string, height, width uint) error - ResizeExecTTY(id string, height, width uint) error - GetContainerStats(id string) (*dockertypes.StatsJSON, error) -} - -// Get a *dockerapi.Client, either using the endpoint passed in, or using -// DOCKER_HOST, DOCKER_TLS_VERIFY, and DOCKER_CERT path per their spec -func getDockerClient(dockerEndpoint string) (*dockerapi.Client, error) { - if len(dockerEndpoint) > 0 { - klog.InfoS("Connecting to docker on the dockerEndpoint", "endpoint", dockerEndpoint) - return dockerapi.NewClientWithOpts(dockerapi.WithHost(dockerEndpoint), dockerapi.WithVersion("")) - } - return dockerapi.NewClientWithOpts(dockerapi.FromEnv) -} - -// ConnectToDockerOrDie creates docker client connecting to docker daemon. -// If the endpoint passed in is "fake://", a fake docker client -// will be returned. The program exits if error occurs. The requestTimeout -// is the timeout for docker requests. If timeout is exceeded, the request -// will be cancelled and throw out an error. If requestTimeout is 0, a default -// value will be applied. -func ConnectToDockerOrDie(dockerEndpoint string, requestTimeout, imagePullProgressDeadline time.Duration) Interface { - client, err := getDockerClient(dockerEndpoint) - if err != nil { - klog.ErrorS(err, "Couldn't connect to docker") - os.Exit(1) - - } - klog.InfoS("Start docker client with request timeout", "timeout", requestTimeout) - return newKubeDockerClient(client, requestTimeout, imagePullProgressDeadline) -} diff --git a/pkg/kubelet/dockershim/libdocker/fake_client.go b/pkg/kubelet/dockershim/libdocker/fake_client.go deleted file mode 100644 index 2b9937b98e5..00000000000 --- a/pkg/kubelet/dockershim/libdocker/fake_client.go +++ /dev/null @@ -1,854 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package libdocker - -import ( - "encoding/json" - "fmt" - "hash/fnv" - "math/rand" - "os" - "reflect" - "strconv" - "strings" - "sync" - "time" - - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - dockerimagetypes "github.com/docker/docker/api/types/image" - - v1 "k8s.io/api/core/v1" - "k8s.io/utils/clock" -) - -type CalledDetail struct { - name string - arguments []interface{} -} - -// NewCalledDetail create a new call detail item. -func NewCalledDetail(name string, arguments []interface{}) CalledDetail { - return CalledDetail{name: name, arguments: arguments} -} - -// FakeDockerClient is a simple fake docker client, so that kubelet can be run for testing without requiring a real docker setup. -type FakeDockerClient struct { - sync.Mutex - Clock clock.Clock - RunningContainerList []dockertypes.Container - ExitedContainerList []dockertypes.Container - ContainerMap map[string]*dockertypes.ContainerJSON - ImageInspects map[string]*dockertypes.ImageInspect - Images []dockertypes.ImageSummary - ImageIDsNeedingAuth map[string]dockertypes.AuthConfig - Errors map[string]error - called []CalledDetail - pulled []string - EnableTrace bool - RandGenerator *rand.Rand - - // Created, Started, Stopped and Removed all contain container docker ID - Created []string - Started []string - Stopped []string - Removed []string - // Images pulled by ref (name or ID). - ImagesPulled []string - - VersionInfo dockertypes.Version - Information dockertypes.Info - ExecInspect *dockertypes.ContainerExecInspect - execCmd []string - EnableSleep bool - ImageHistoryMap map[string][]dockerimagetypes.HistoryResponseItem - ContainerStatsMap map[string]*dockertypes.StatsJSON -} - -const ( - // Notice that if someday we also have minimum docker version requirement, this should also be updated. - fakeDockerVersion = "1.13.1" - - fakeImageSize = 1024 - - // Docker prepends '/' to the container name. - dockerNamePrefix = "/" -) - -func NewFakeDockerClient() *FakeDockerClient { - return &FakeDockerClient{ - // Docker's API version does not include the patch number. - VersionInfo: dockertypes.Version{Version: fakeDockerVersion, APIVersion: strings.TrimSuffix(MinimumDockerAPIVersion, ".0")}, - Errors: make(map[string]error), - ContainerMap: make(map[string]*dockertypes.ContainerJSON), - Clock: clock.RealClock{}, - // default this to true, so that we trace calls, image pulls and container lifecycle - EnableTrace: true, - ExecInspect: &dockertypes.ContainerExecInspect{}, - ImageInspects: make(map[string]*dockertypes.ImageInspect), - ImageIDsNeedingAuth: make(map[string]dockertypes.AuthConfig), - RandGenerator: rand.New(rand.NewSource(time.Now().UnixNano())), - } -} - -func (f *FakeDockerClient) WithClock(c clock.Clock) *FakeDockerClient { - f.Lock() - defer f.Unlock() - f.Clock = c - return f -} - -func (f *FakeDockerClient) WithVersion(version, apiVersion string) *FakeDockerClient { - f.Lock() - defer f.Unlock() - f.VersionInfo = dockertypes.Version{Version: version, APIVersion: apiVersion} - return f -} - -func (f *FakeDockerClient) WithTraceDisabled() *FakeDockerClient { - f.Lock() - defer f.Unlock() - f.EnableTrace = false - return f -} - -func (f *FakeDockerClient) WithRandSource(source rand.Source) *FakeDockerClient { - f.Lock() - defer f.Unlock() - f.RandGenerator = rand.New(source) - return f -} - -func (f *FakeDockerClient) appendCalled(callDetail CalledDetail) { - if f.EnableTrace { - f.called = append(f.called, callDetail) - } -} - -func (f *FakeDockerClient) appendPulled(pull string) { - if f.EnableTrace { - f.pulled = append(f.pulled, pull) - } -} - -func (f *FakeDockerClient) appendContainerTrace(traceCategory string, containerName string) { - if !f.EnableTrace { - return - } - switch traceCategory { - case "Created": - f.Created = append(f.Created, containerName) - case "Started": - f.Started = append(f.Started, containerName) - case "Stopped": - f.Stopped = append(f.Stopped, containerName) - case "Removed": - f.Removed = append(f.Removed, containerName) - } -} - -func (f *FakeDockerClient) InjectError(fn string, err error) { - f.Lock() - defer f.Unlock() - f.Errors[fn] = err -} - -func (f *FakeDockerClient) InjectErrors(errs map[string]error) { - f.Lock() - defer f.Unlock() - for fn, err := range errs { - f.Errors[fn] = err - } -} - -func (f *FakeDockerClient) ClearErrors() { - f.Lock() - defer f.Unlock() - f.Errors = map[string]error{} -} - -func (f *FakeDockerClient) ClearCalls() { - f.Lock() - defer f.Unlock() - f.called = []CalledDetail{} - f.pulled = []string{} - f.Created = []string{} - f.Started = []string{} - f.Stopped = []string{} - f.Removed = []string{} -} - -func (f *FakeDockerClient) getCalledNames() []string { - names := []string{} - for _, detail := range f.called { - names = append(names, detail.name) - } - return names -} - -// Because the new data type returned by engine-api is too complex to manually initialize, we need a -// fake container which is easier to initialize. -type FakeContainer struct { - ID string - Name string - Running bool - ExitCode int - Pid int - CreatedAt time.Time - StartedAt time.Time - FinishedAt time.Time - Config *dockercontainer.Config - HostConfig *dockercontainer.HostConfig -} - -// convertFakeContainer converts the fake container to real container -func convertFakeContainer(f *FakeContainer) *dockertypes.ContainerJSON { - if f.Config == nil { - f.Config = &dockercontainer.Config{} - } - if f.HostConfig == nil { - f.HostConfig = &dockercontainer.HostConfig{} - } - fakeRWSize := int64(40) - return &dockertypes.ContainerJSON{ - ContainerJSONBase: &dockertypes.ContainerJSONBase{ - ID: f.ID, - Name: f.Name, - Image: f.Config.Image, - State: &dockertypes.ContainerState{ - Running: f.Running, - ExitCode: f.ExitCode, - Pid: f.Pid, - StartedAt: dockerTimestampToString(f.StartedAt), - FinishedAt: dockerTimestampToString(f.FinishedAt), - }, - Created: dockerTimestampToString(f.CreatedAt), - HostConfig: f.HostConfig, - SizeRw: &fakeRWSize, - }, - Config: f.Config, - NetworkSettings: &dockertypes.NetworkSettings{}, - } -} - -func (f *FakeDockerClient) SetFakeContainers(containers []*FakeContainer) { - f.Lock() - defer f.Unlock() - // Reset the lists and the map. - f.ContainerMap = map[string]*dockertypes.ContainerJSON{} - f.RunningContainerList = []dockertypes.Container{} - f.ExitedContainerList = []dockertypes.Container{} - - for i := range containers { - c := containers[i] - f.ContainerMap[c.ID] = convertFakeContainer(c) - container := dockertypes.Container{ - Names: []string{c.Name}, - ID: c.ID, - } - if c.Config != nil { - container.Labels = c.Config.Labels - } - if c.Running { - f.RunningContainerList = append(f.RunningContainerList, container) - } else { - f.ExitedContainerList = append(f.ExitedContainerList, container) - } - } -} - -func (f *FakeDockerClient) AssertCalls(calls []string) (err error) { - f.Lock() - defer f.Unlock() - - if !reflect.DeepEqual(calls, f.getCalledNames()) { - err = fmt.Errorf("expected %#v, got %#v", calls, f.getCalledNames()) - } - - return -} - -func (f *FakeDockerClient) AssertCallDetails(calls ...CalledDetail) (err error) { - f.Lock() - defer f.Unlock() - - if !reflect.DeepEqual(calls, f.called) { - err = fmt.Errorf("expected %#v, got %#v", calls, f.called) - } - - return -} - -func (f *FakeDockerClient) popError(op string) error { - if f.Errors == nil { - return nil - } - err, ok := f.Errors[op] - if ok { - delete(f.Errors, op) - return err - } - return nil -} - -// ListContainers is a test-spy implementation of Interface.ListContainers. -// It adds an entry "list" to the internal method call record. -func (f *FakeDockerClient) ListContainers(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "list"}) - err := f.popError("list") - containerList := append([]dockertypes.Container{}, f.RunningContainerList...) - if options.All { - // Although the container is not sorted, but the container with the same name should be in order, - // that is enough for us now. - containerList = append(containerList, f.ExitedContainerList...) - } - // Filters containers with id, only support 1 id. - idFilters := options.Filters.Get("id") - if len(idFilters) != 0 { - var filtered []dockertypes.Container - for _, container := range containerList { - for _, idFilter := range idFilters { - if container.ID == idFilter { - filtered = append(filtered, container) - break - } - } - } - containerList = filtered - } - // Filters containers with status, only support 1 status. - statusFilters := options.Filters.Get("status") - if len(statusFilters) == 1 { - var filtered []dockertypes.Container - for _, container := range containerList { - for _, statusFilter := range statusFilters { - if toDockerContainerStatus(container.Status) == statusFilter { - filtered = append(filtered, container) - break - } - } - } - containerList = filtered - } - // Filters containers with label filter. - labelFilters := options.Filters.Get("label") - if len(labelFilters) != 0 { - var filtered []dockertypes.Container - for _, container := range containerList { - match := true - for _, labelFilter := range labelFilters { - kv := strings.Split(labelFilter, "=") - if len(kv) != 2 { - return nil, fmt.Errorf("invalid label filter %q", labelFilter) - } - if container.Labels[kv[0]] != kv[1] { - match = false - break - } - } - if match { - filtered = append(filtered, container) - } - } - containerList = filtered - } - return containerList, err -} - -func toDockerContainerStatus(state string) string { - switch { - case strings.HasPrefix(state, StatusCreatedPrefix): - return "created" - case strings.HasPrefix(state, StatusRunningPrefix): - return "running" - case strings.HasPrefix(state, StatusExitedPrefix): - return "exited" - default: - return "unknown" - } -} - -// InspectContainer is a test-spy implementation of Interface.InspectContainer. -// It adds an entry "inspect" to the internal method call record. -func (f *FakeDockerClient) InspectContainer(id string) (*dockertypes.ContainerJSON, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "inspect_container"}) - err := f.popError("inspect_container") - if container, ok := f.ContainerMap[id]; ok { - return container, err - } - if err != nil { - // Use the custom error if it exists. - return nil, err - } - return nil, fmt.Errorf("container %q not found", id) -} - -// InspectContainerWithSize is a test-spy implementation of Interface.InspectContainerWithSize. -// It adds an entry "inspect" to the internal method call record. -func (f *FakeDockerClient) InspectContainerWithSize(id string) (*dockertypes.ContainerJSON, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "inspect_container_withsize"}) - err := f.popError("inspect_container_withsize") - if container, ok := f.ContainerMap[id]; ok { - return container, err - } - if err != nil { - // Use the custom error if it exists. - return nil, err - } - return nil, fmt.Errorf("container %q not found", id) -} - -// InspectImageByRef is a test-spy implementation of Interface.InspectImageByRef. -// It adds an entry "inspect" to the internal method call record. -func (f *FakeDockerClient) InspectImageByRef(name string) (*dockertypes.ImageInspect, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "inspect_image"}) - if err := f.popError("inspect_image"); err != nil { - return nil, err - } - if result, ok := f.ImageInspects[name]; ok { - return result, nil - } - return nil, ImageNotFoundError{name} -} - -// InspectImageByID is a test-spy implementation of Interface.InspectImageByID. -// It adds an entry "inspect" to the internal method call record. -func (f *FakeDockerClient) InspectImageByID(name string) (*dockertypes.ImageInspect, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "inspect_image"}) - if err := f.popError("inspect_image"); err != nil { - return nil, err - } - if result, ok := f.ImageInspects[name]; ok { - return result, nil - } - return nil, ImageNotFoundError{name} -} - -// Sleeps random amount of time with the normal distribution with given mean and stddev -// (in milliseconds), we never sleep less than cutOffMillis -func (f *FakeDockerClient) normalSleep(mean, stdDev, cutOffMillis int) { - if !f.EnableSleep { - return - } - cutoff := (time.Duration)(cutOffMillis) * time.Millisecond - delay := (time.Duration)(f.RandGenerator.NormFloat64()*float64(stdDev)+float64(mean)) * time.Millisecond - if delay < cutoff { - delay = cutoff - } - time.Sleep(delay) -} - -// GetFakeContainerID generates a fake container id from container name with a hash. -func GetFakeContainerID(name string) string { - hash := fnv.New64a() - hash.Write([]byte(name)) - return strconv.FormatUint(hash.Sum64(), 16) -} - -// CreateContainer is a test-spy implementation of Interface.CreateContainer. -// It adds an entry "create" to the internal method call record. -func (f *FakeDockerClient) CreateContainer(c dockertypes.ContainerCreateConfig) (*dockercontainer.ContainerCreateCreatedBody, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "create"}) - if err := f.popError("create"); err != nil { - return nil, err - } - // This is not a very good fake. We'll just add this container's name to the list. - name := dockerNamePrefix + c.Name - id := GetFakeContainerID(name) - f.appendContainerTrace("Created", id) - timestamp := f.Clock.Now() - // The newest container should be in front, because we assume so in GetPodStatus() - f.RunningContainerList = append([]dockertypes.Container{ - {ID: id, Names: []string{name}, Image: c.Config.Image, Created: timestamp.Unix(), State: StatusCreatedPrefix, Labels: c.Config.Labels}, - }, f.RunningContainerList...) - f.ContainerMap[id] = convertFakeContainer(&FakeContainer{ - ID: id, Name: name, Config: c.Config, HostConfig: c.HostConfig, CreatedAt: timestamp}) - - f.normalSleep(100, 25, 25) - - return &dockercontainer.ContainerCreateCreatedBody{ID: id}, nil -} - -// StartContainer is a test-spy implementation of Interface.StartContainer. -// It adds an entry "start" to the internal method call record. -func (f *FakeDockerClient) StartContainer(id string) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "start"}) - if err := f.popError("start"); err != nil { - return err - } - f.appendContainerTrace("Started", id) - container, ok := f.ContainerMap[id] - if container.HostConfig.NetworkMode.IsContainer() { - hostContainerID := container.HostConfig.NetworkMode.ConnectedContainer() - found := false - for _, container := range f.RunningContainerList { - if container.ID == hostContainerID { - found = true - } - } - if !found { - return fmt.Errorf("failed to start container \"%s\": Error response from daemon: cannot join network of a non running container: %s", id, hostContainerID) - } - } - timestamp := f.Clock.Now() - if !ok { - container = convertFakeContainer(&FakeContainer{ID: id, Name: id, CreatedAt: timestamp}) - } - container.State.Running = true - container.State.Pid = os.Getpid() - container.State.StartedAt = dockerTimestampToString(timestamp) - r := f.RandGenerator.Uint32() - container.NetworkSettings.IPAddress = fmt.Sprintf("10.%d.%d.%d", byte(r>>16), byte(r>>8), byte(r)) - f.ContainerMap[id] = container - f.updateContainerStatus(id, StatusRunningPrefix) - f.normalSleep(200, 50, 50) - return nil -} - -// StopContainer is a test-spy implementation of Interface.StopContainer. -// It adds an entry "stop" to the internal method call record. -func (f *FakeDockerClient) StopContainer(id string, timeout time.Duration) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "stop"}) - if err := f.popError("stop"); err != nil { - return err - } - f.appendContainerTrace("Stopped", id) - // Container status should be Updated before container moved to ExitedContainerList - f.updateContainerStatus(id, StatusExitedPrefix) - var newList []dockertypes.Container - for _, container := range f.RunningContainerList { - if container.ID == id { - // The newest exited container should be in front. Because we assume so in GetPodStatus() - f.ExitedContainerList = append([]dockertypes.Container{container}, f.ExitedContainerList...) - continue - } - newList = append(newList, container) - } - f.RunningContainerList = newList - container, ok := f.ContainerMap[id] - if !ok { - container = convertFakeContainer(&FakeContainer{ - ID: id, - Name: id, - Running: false, - StartedAt: time.Now().Add(-time.Second), - FinishedAt: time.Now(), - }) - } else { - container.State.FinishedAt = dockerTimestampToString(f.Clock.Now()) - container.State.Running = false - } - f.ContainerMap[id] = container - f.normalSleep(200, 50, 50) - return nil -} - -func (f *FakeDockerClient) RemoveContainer(id string, opts dockertypes.ContainerRemoveOptions) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "remove"}) - err := f.popError("remove") - if err != nil { - return err - } - for i := range f.ExitedContainerList { - if f.ExitedContainerList[i].ID == id { - delete(f.ContainerMap, id) - f.ExitedContainerList = append(f.ExitedContainerList[:i], f.ExitedContainerList[i+1:]...) - f.appendContainerTrace("Removed", id) - return nil - } - - } - for i := range f.RunningContainerList { - // allow removal of running containers which are not running - if f.RunningContainerList[i].ID == id && !f.ContainerMap[id].State.Running { - delete(f.ContainerMap, id) - f.RunningContainerList = append(f.RunningContainerList[:i], f.RunningContainerList[i+1:]...) - f.appendContainerTrace("Removed", id) - return nil - } - } - // To be a good fake, report error if container is not stopped. - return fmt.Errorf("container not stopped") -} - -func (f *FakeDockerClient) UpdateContainerResources(id string, updateConfig dockercontainer.UpdateConfig) error { - return nil -} - -// Logs is a test-spy implementation of Interface.Logs. -// It adds an entry "logs" to the internal method call record. -func (f *FakeDockerClient) Logs(id string, opts dockertypes.ContainerLogsOptions, sopts StreamOptions) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "logs"}) - return f.popError("logs") -} - -func (f *FakeDockerClient) isAuthorizedForImage(image string, auth dockertypes.AuthConfig) bool { - if reqd, exists := f.ImageIDsNeedingAuth[image]; !exists { - return true // no auth needed - } else { - return auth.Username == reqd.Username && auth.Password == reqd.Password - } -} - -// PullImage is a test-spy implementation of Interface.PullImage. -// It adds an entry "pull" to the internal method call record. -func (f *FakeDockerClient) PullImage(image string, auth dockertypes.AuthConfig, opts dockertypes.ImagePullOptions) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "pull"}) - err := f.popError("pull") - if err == nil { - if !f.isAuthorizedForImage(image, auth) { - return ImageNotFoundError{ID: image} - } - - authJson, _ := json.Marshal(auth) - inspect := createImageInspectFromRef(image) - f.ImageInspects[image] = inspect - f.appendPulled(fmt.Sprintf("%s using %s", image, string(authJson))) - f.Images = append(f.Images, *createImageFromImageInspect(*inspect)) - f.ImagesPulled = append(f.ImagesPulled, image) - } - return err -} - -func (f *FakeDockerClient) Version() (*dockertypes.Version, error) { - f.Lock() - defer f.Unlock() - v := f.VersionInfo - return &v, f.popError("version") -} - -func (f *FakeDockerClient) Info() (*dockertypes.Info, error) { - return &f.Information, nil -} - -func (f *FakeDockerClient) CreateExec(id string, opts dockertypes.ExecConfig) (*dockertypes.IDResponse, error) { - f.Lock() - defer f.Unlock() - f.execCmd = opts.Cmd - f.appendCalled(CalledDetail{name: "create_exec"}) - return &dockertypes.IDResponse{ID: "12345678"}, nil -} - -func (f *FakeDockerClient) StartExec(startExec string, opts dockertypes.ExecStartCheck, sopts StreamOptions) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "start_exec"}) - return nil -} - -func (f *FakeDockerClient) AttachToContainer(id string, opts dockertypes.ContainerAttachOptions, sopts StreamOptions) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "attach"}) - return nil -} - -func (f *FakeDockerClient) InspectExec(id string) (*dockertypes.ContainerExecInspect, error) { - return f.ExecInspect, f.popError("inspect_exec") -} - -func (f *FakeDockerClient) ListImages(opts dockertypes.ImageListOptions) ([]dockertypes.ImageSummary, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "list_images"}) - err := f.popError("list_images") - return f.Images, err -} - -func (f *FakeDockerClient) RemoveImage(image string, opts dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDeleteResponseItem, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "remove_image", arguments: []interface{}{image, opts}}) - err := f.popError("remove_image") - if err == nil { - for i := range f.Images { - if f.Images[i].ID == image { - f.Images = append(f.Images[:i], f.Images[i+1:]...) - break - } - } - } - return []dockertypes.ImageDeleteResponseItem{{Deleted: image}}, err -} - -func (f *FakeDockerClient) InjectImages(images []dockertypes.ImageSummary) { - f.Lock() - defer f.Unlock() - f.Images = append(f.Images, images...) - for _, i := range images { - f.ImageInspects[i.ID] = createImageInspectFromImage(i) - } -} - -func (f *FakeDockerClient) MakeImagesPrivate(images []dockertypes.ImageSummary, auth dockertypes.AuthConfig) { - f.Lock() - defer f.Unlock() - for _, i := range images { - f.ImageIDsNeedingAuth[i.ID] = auth - } -} - -func (f *FakeDockerClient) ResetImages() { - f.Lock() - defer f.Unlock() - f.Images = []dockertypes.ImageSummary{} - f.ImageInspects = make(map[string]*dockertypes.ImageInspect) - f.ImageIDsNeedingAuth = make(map[string]dockertypes.AuthConfig) -} - -func (f *FakeDockerClient) InjectImageInspects(inspects []dockertypes.ImageInspect) { - f.Lock() - defer f.Unlock() - for i := range inspects { - inspect := inspects[i] - f.Images = append(f.Images, *createImageFromImageInspect(inspect)) - f.ImageInspects[inspect.ID] = &inspect - } -} - -func (f *FakeDockerClient) updateContainerStatus(id, status string) { - for i := range f.RunningContainerList { - if f.RunningContainerList[i].ID == id { - f.RunningContainerList[i].Status = status - } - } -} - -func (f *FakeDockerClient) ResizeExecTTY(id string, height, width uint) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "resize_exec"}) - return nil -} - -func (f *FakeDockerClient) ResizeContainerTTY(id string, height, width uint) error { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "resize_container"}) - return nil -} - -func createImageInspectFromRef(ref string) *dockertypes.ImageInspect { - return &dockertypes.ImageInspect{ - ID: ref, - RepoTags: []string{ref}, - // Image size is required to be non-zero for CRI integration. - VirtualSize: fakeImageSize, - Size: fakeImageSize, - Config: &dockercontainer.Config{}, - } -} - -func createImageInspectFromImage(image dockertypes.ImageSummary) *dockertypes.ImageInspect { - return &dockertypes.ImageInspect{ - ID: image.ID, - RepoTags: image.RepoTags, - // Image size is required to be non-zero for CRI integration. - VirtualSize: fakeImageSize, - Size: fakeImageSize, - Config: &dockercontainer.Config{}, - } -} - -func createImageFromImageInspect(inspect dockertypes.ImageInspect) *dockertypes.ImageSummary { - return &dockertypes.ImageSummary{ - ID: inspect.ID, - RepoTags: inspect.RepoTags, - // Image size is required to be non-zero for CRI integration. - VirtualSize: fakeImageSize, - Size: fakeImageSize, - } -} - -// dockerTimestampToString converts the timestamp to string -func dockerTimestampToString(t time.Time) string { - return t.Format(time.RFC3339Nano) -} - -func (f *FakeDockerClient) ImageHistory(id string) ([]dockerimagetypes.HistoryResponseItem, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "image_history"}) - history := f.ImageHistoryMap[id] - return history, nil -} - -func (f *FakeDockerClient) InjectImageHistory(data map[string][]dockerimagetypes.HistoryResponseItem) { - f.Lock() - defer f.Unlock() - f.ImageHistoryMap = data -} - -// FakeDockerPuller is meant to be a simple wrapper around FakeDockerClient. -// Please do not add more functionalities to it. -type FakeDockerPuller struct { - client Interface -} - -func (f *FakeDockerPuller) Pull(image string, _ []v1.Secret) error { - return f.client.PullImage(image, dockertypes.AuthConfig{}, dockertypes.ImagePullOptions{}) -} - -func (f *FakeDockerPuller) GetImageRef(image string) (string, error) { - _, err := f.client.InspectImageByRef(image) - if err != nil && IsImageNotFoundError(err) { - return "", nil - } - return image, err -} - -func (f *FakeDockerClient) InjectContainerStats(data map[string]*dockertypes.StatsJSON) { - f.Lock() - defer f.Unlock() - f.ContainerStatsMap = data -} - -func (f *FakeDockerClient) GetContainerStats(id string) (*dockertypes.StatsJSON, error) { - f.Lock() - defer f.Unlock() - f.appendCalled(CalledDetail{name: "get_container_stats"}) - stats, ok := f.ContainerStatsMap[id] - if !ok { - return nil, fmt.Errorf("container %q not found", id) - } - return stats, nil -} diff --git a/pkg/kubelet/dockershim/libdocker/helpers.go b/pkg/kubelet/dockershim/libdocker/helpers.go deleted file mode 100644 index 57918629ad6..00000000000 --- a/pkg/kubelet/dockershim/libdocker/helpers.go +++ /dev/null @@ -1,166 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package libdocker - -import ( - "strings" - "time" - - dockerref "github.com/docker/distribution/reference" - dockertypes "github.com/docker/docker/api/types" - godigest "github.com/opencontainers/go-digest" - "k8s.io/klog/v2" -) - -// ParseDockerTimestamp parses the timestamp returned by Interface from string to time.Time -func ParseDockerTimestamp(s string) (time.Time, error) { - // Timestamp returned by Docker is in time.RFC3339Nano format. - return time.Parse(time.RFC3339Nano, s) -} - -// matchImageTagOrSHA checks if the given image specifier is a valid image ref, -// and that it matches the given image. It should fail on things like image IDs -// (config digests) and other digest-only references, but succeed on image names -// (`foo`), tag references (`foo:bar`), and manifest digest references -// (`foo@sha256:xyz`). -func matchImageTagOrSHA(inspected dockertypes.ImageInspect, image string) bool { - // The image string follows the grammar specified here - // https://github.com/docker/distribution/blob/master/reference/reference.go#L4 - named, err := dockerref.ParseNormalizedNamed(image) - if err != nil { - klog.V(4).InfoS("Couldn't parse image reference", "image", image, "err", err) - return false - } - _, isTagged := named.(dockerref.Tagged) - digest, isDigested := named.(dockerref.Digested) - if !isTagged && !isDigested { - // No Tag or SHA specified, so just return what we have - return true - } - - if isTagged { - // Check the RepoTags for a match. - for _, tag := range inspected.RepoTags { - // An image name (without the tag/digest) can be [hostname '/'] component ['/' component]* - // Because either the RepoTag or the name *may* contain the - // hostname or not, we only check for the suffix match. - if strings.HasSuffix(image, tag) || strings.HasSuffix(tag, image) { - return true - } else { - // TODO: We need to remove this hack when project atomic based - // docker distro(s) like centos/fedora/rhel image fix problems on - // their end. - // Say the tag is "docker.io/busybox:latest" - // and the image is "docker.io/library/busybox:latest" - t, err := dockerref.ParseNormalizedNamed(tag) - if err != nil { - continue - } - // the parsed/normalized tag will look like - // reference.taggedReference { - // namedRepository: reference.repository { - // domain: "docker.io", - // path: "library/busybox" - // }, - // tag: "latest" - // } - // If it does not have tags then we bail out - t2, ok := t.(dockerref.Tagged) - if !ok { - continue - } - // normalized tag would look like "docker.io/library/busybox:latest" - // note the library get added in the string - normalizedTag := t2.String() - if normalizedTag == "" { - continue - } - if strings.HasSuffix(image, normalizedTag) || strings.HasSuffix(normalizedTag, image) { - return true - } - } - } - } - - if isDigested { - for _, repoDigest := range inspected.RepoDigests { - named, err := dockerref.ParseNormalizedNamed(repoDigest) - if err != nil { - klog.V(4).InfoS("Couldn't parse image RepoDigest reference", "digest", repoDigest, "err", err) - continue - } - if d, isDigested := named.(dockerref.Digested); isDigested { - if digest.Digest().Algorithm().String() == d.Digest().Algorithm().String() && - digest.Digest().Hex() == d.Digest().Hex() { - return true - } - } - } - - // process the ID as a digest - id, err := godigest.Parse(inspected.ID) - if err != nil { - klog.V(4).InfoS("Couldn't parse image ID reference", "imageID", id, "err", err) - return false - } - if digest.Digest().Algorithm().String() == id.Algorithm().String() && digest.Digest().Hex() == id.Hex() { - return true - } - } - klog.V(4).InfoS("Inspected image ID does not match image", "inspectedImageID", inspected.ID, "image", image) - return false -} - -// matchImageIDOnly checks that the given image specifier is a digest-only -// reference, and that it matches the given image. -func matchImageIDOnly(inspected dockertypes.ImageInspect, image string) bool { - // If the image ref is literally equal to the inspected image's ID, - // just return true here (this might be the case for Docker 1.9, - // where we won't have a digest for the ID) - if inspected.ID == image { - return true - } - - // Otherwise, we should try actual parsing to be more correct - ref, err := dockerref.Parse(image) - if err != nil { - klog.V(4).InfoS("Couldn't parse image reference", "image", image, "err", err) - return false - } - - digest, isDigested := ref.(dockerref.Digested) - if !isDigested { - klog.V(4).InfoS("The image reference was not a digest reference", "image", image) - return false - } - - id, err := godigest.Parse(inspected.ID) - if err != nil { - klog.V(4).InfoS("Couldn't parse image ID reference", "imageID", id, "err", err) - return false - } - - if digest.Digest().Algorithm().String() == id.Algorithm().String() && digest.Digest().Hex() == id.Hex() { - return true - } - - klog.V(4).InfoS("The image reference does not directly refer to the given image's ID", "image", image, "inspectedImageID", inspected.ID) - return false -} diff --git a/pkg/kubelet/dockershim/libdocker/helpers_test.go b/pkg/kubelet/dockershim/libdocker/helpers_test.go deleted file mode 100644 index e70f0055254..00000000000 --- a/pkg/kubelet/dockershim/libdocker/helpers_test.go +++ /dev/null @@ -1,273 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package libdocker - -import ( - "fmt" - "testing" - - dockertypes "github.com/docker/docker/api/types" - "github.com/stretchr/testify/assert" -) - -func TestMatchImageTagOrSHA(t *testing.T) { - for i, testCase := range []struct { - Inspected dockertypes.ImageInspect - Image string - Output bool - }{ - { - Inspected: dockertypes.ImageInspect{RepoTags: []string{"ubuntu:latest"}}, - Image: "ubuntu", - Output: true, - }, - { - Inspected: dockertypes.ImageInspect{RepoTags: []string{"ubuntu:14.04"}}, - Image: "ubuntu:latest", - Output: false, - }, - { - Inspected: dockertypes.ImageInspect{RepoTags: []string{"colemickens/hyperkube-amd64:217.9beff63"}}, - Image: "colemickens/hyperkube-amd64:217.9beff63", - Output: true, - }, - { - Inspected: dockertypes.ImageInspect{RepoTags: []string{"colemickens/hyperkube-amd64:217.9beff63"}}, - Image: "docker.io/colemickens/hyperkube-amd64:217.9beff63", - Output: true, - }, - { - Inspected: dockertypes.ImageInspect{RepoTags: []string{"docker.io/kubernetes/pause:latest"}}, - Image: "kubernetes/pause:latest", - Output: true, - }, - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - }, - Image: "myimage@sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - Output: true, - }, - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - }, - Image: "myimage@sha256:2208f7a29005", - Output: false, - }, - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - }, - Image: "myimage@sha256:2208", - Output: false, - }, - { - // mismatched ID is ignored - Inspected: dockertypes.ImageInspect{ - ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - }, - Image: "myimage@sha256:0000f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - Output: false, - }, - { - // invalid digest is ignored - Inspected: dockertypes.ImageInspect{ - ID: "sha256:unparseable", - }, - Image: "myimage@sha256:unparseable", - Output: false, - }, - { - // v1 schema images can be pulled in one format and returned in another - Inspected: dockertypes.ImageInspect{ - ID: "sha256:9bbdf247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227", - RepoDigests: []string{"centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf"}, - }, - Image: "centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - Output: true, - }, - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:9bbdf247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227", - RepoTags: []string{"docker.io/busybox:latest"}, - }, - Image: "docker.io/library/busybox:latest", - Output: true, - }, - { - // RepoDigest match is required - Inspected: dockertypes.ImageInspect{ - ID: "", - RepoDigests: []string{"docker.io/centos/ruby-23-centos7@sha256:000084acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf"}, - }, - Image: "centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - Output: false, - }, - { - // RepoDigest match is allowed - Inspected: dockertypes.ImageInspect{ - ID: "sha256:9bbdf247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227", - RepoDigests: []string{"docker.io/centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf"}, - }, - Image: "centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - Output: true, - }, - { - // RepoDigest and ID are checked - Inspected: dockertypes.ImageInspect{ - ID: "sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - RepoDigests: []string{"docker.io/centos/ruby-23-centos7@sha256:9bbdf247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227"}, - }, - Image: "centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - Output: true, - }, - { - // unparseable RepoDigests are skipped - Inspected: dockertypes.ImageInspect{ - ID: "sha256:9bbdf247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227", - RepoDigests: []string{ - "centos/ruby-23-centos7@sha256:unparseable", - "docker.io/centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - }, - }, - Image: "centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - Output: true, - }, - { - // unparseable RepoDigest is ignored - Inspected: dockertypes.ImageInspect{ - ID: "sha256:9bbdf247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227", - RepoDigests: []string{"docker.io/centos/ruby-23-centos7@sha256:unparseable"}, - }, - Image: "centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - Output: false, - }, - { - // unparseable image digest is ignored - Inspected: dockertypes.ImageInspect{ - ID: "sha256:9bbdf247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227", - RepoDigests: []string{"docker.io/centos/ruby-23-centos7@sha256:unparseable"}, - }, - Image: "centos/ruby-23-centos7@sha256:unparseable", - Output: false, - }, - { - // prefix match is rejected for ID and RepoDigest - Inspected: dockertypes.ImageInspect{ - ID: "sha256:unparseable", - RepoDigests: []string{"docker.io/centos/ruby-23-centos7@sha256:unparseable"}, - }, - Image: "sha256:unparseable", - Output: false, - }, - { - // possible SHA prefix match is rejected for ID and RepoDigest because it is not in the named format - Inspected: dockertypes.ImageInspect{ - ID: "sha256:0000f247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227", - RepoDigests: []string{"docker.io/centos/ruby-23-centos7@sha256:0000f247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227"}, - }, - Image: "sha256:0000", - Output: false, - }, - } { - match := matchImageTagOrSHA(testCase.Inspected, testCase.Image) - assert.Equal(t, testCase.Output, match, testCase.Image+fmt.Sprintf(" is not a match (%d)", i)) - } -} - -func TestMatchImageIDOnly(t *testing.T) { - for i, testCase := range []struct { - Inspected dockertypes.ImageInspect - Image string - Output bool - }{ - // shouldn't match names or tagged names - { - Inspected: dockertypes.ImageInspect{RepoTags: []string{"ubuntu:latest"}}, - Image: "ubuntu", - Output: false, - }, - { - Inspected: dockertypes.ImageInspect{RepoTags: []string{"colemickens/hyperkube-amd64:217.9beff63"}}, - Image: "colemickens/hyperkube-amd64:217.9beff63", - Output: false, - }, - // should match name@digest refs if they refer to the image ID (but only the full ID) - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - }, - Image: "myimage@sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - Output: true, - }, - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - }, - Image: "myimage@sha256:2208f7a29005", - Output: false, - }, - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - }, - Image: "myimage@sha256:2208", - Output: false, - }, - // should match when the IDs are literally the same - { - Inspected: dockertypes.ImageInspect{ - ID: "foobar", - }, - Image: "foobar", - Output: true, - }, - // shouldn't match mismatched IDs - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:2208f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - }, - Image: "myimage@sha256:0000f7a29005d226d1ee33a63e33af1f47af6156c740d7d23c7948e8d282d53d", - Output: false, - }, - // shouldn't match invalid IDs or refs - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:unparseable", - }, - Image: "myimage@sha256:unparseable", - Output: false, - }, - // shouldn't match against repo digests - { - Inspected: dockertypes.ImageInspect{ - ID: "sha256:9bbdf247c91345f0789c10f50a57e36a667af1189687ad1de88a6243d05a2227", - RepoDigests: []string{"centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf"}, - }, - Image: "centos/ruby-23-centos7@sha256:940584acbbfb0347272112d2eb95574625c0c60b4e2fdadb139de5859cf754bf", - Output: false, - }, - } { - match := matchImageIDOnly(testCase.Inspected, testCase.Image) - assert.Equal(t, testCase.Output, match, fmt.Sprintf("%s is not a match (%d)", testCase.Image, i)) - } - -} diff --git a/pkg/kubelet/dockershim/libdocker/instrumented_client.go b/pkg/kubelet/dockershim/libdocker/instrumented_client.go deleted file mode 100644 index 1bd9b77ee07..00000000000 --- a/pkg/kubelet/dockershim/libdocker/instrumented_client.go +++ /dev/null @@ -1,275 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package libdocker - -import ( - "time" - - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - dockerimagetypes "github.com/docker/docker/api/types/image" - - "k8s.io/kubernetes/pkg/kubelet/dockershim/metrics" -) - -// instrumentedInterface wraps the Interface and records the operations -// and errors metrics. -type instrumentedInterface struct { - client Interface -} - -// NewInstrumentedInterface creates an instrumented Interface from an existing Interface. -func NewInstrumentedInterface(dockerClient Interface) Interface { - return instrumentedInterface{ - client: dockerClient, - } -} - -// recordOperation records the duration of the operation. -func recordOperation(operation string, start time.Time) { - metrics.DockerOperations.WithLabelValues(operation).Inc() - metrics.DockerOperationsLatency.WithLabelValues(operation).Observe(metrics.SinceInSeconds(start)) -} - -// recordError records error for metric if an error occurred. -func recordError(operation string, err error) { - if err != nil { - if _, ok := err.(operationTimeout); ok { - metrics.DockerOperationsTimeout.WithLabelValues(operation).Inc() - } - // Docker operation timeout error is also a docker error, so we don't add else here. - metrics.DockerOperationsErrors.WithLabelValues(operation).Inc() - } -} - -func (in instrumentedInterface) ListContainers(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error) { - const operation = "list_containers" - defer recordOperation(operation, time.Now()) - - out, err := in.client.ListContainers(options) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) InspectContainer(id string) (*dockertypes.ContainerJSON, error) { - const operation = "inspect_container" - defer recordOperation(operation, time.Now()) - - out, err := in.client.InspectContainer(id) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) InspectContainerWithSize(id string) (*dockertypes.ContainerJSON, error) { - const operation = "inspect_container_withsize" - defer recordOperation(operation, time.Now()) - - out, err := in.client.InspectContainerWithSize(id) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) CreateContainer(opts dockertypes.ContainerCreateConfig) (*dockercontainer.ContainerCreateCreatedBody, error) { - const operation = "create_container" - defer recordOperation(operation, time.Now()) - - out, err := in.client.CreateContainer(opts) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) StartContainer(id string) error { - const operation = "start_container" - defer recordOperation(operation, time.Now()) - - err := in.client.StartContainer(id) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) StopContainer(id string, timeout time.Duration) error { - const operation = "stop_container" - defer recordOperation(operation, time.Now()) - - err := in.client.StopContainer(id, timeout) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) RemoveContainer(id string, opts dockertypes.ContainerRemoveOptions) error { - const operation = "remove_container" - defer recordOperation(operation, time.Now()) - - err := in.client.RemoveContainer(id, opts) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) UpdateContainerResources(id string, updateConfig dockercontainer.UpdateConfig) error { - const operation = "update_container" - defer recordOperation(operation, time.Now()) - - err := in.client.UpdateContainerResources(id, updateConfig) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) InspectImageByRef(image string) (*dockertypes.ImageInspect, error) { - const operation = "inspect_image" - defer recordOperation(operation, time.Now()) - - out, err := in.client.InspectImageByRef(image) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) InspectImageByID(image string) (*dockertypes.ImageInspect, error) { - const operation = "inspect_image" - defer recordOperation(operation, time.Now()) - - out, err := in.client.InspectImageByID(image) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) ListImages(opts dockertypes.ImageListOptions) ([]dockertypes.ImageSummary, error) { - const operation = "list_images" - defer recordOperation(operation, time.Now()) - - out, err := in.client.ListImages(opts) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) PullImage(imageID string, auth dockertypes.AuthConfig, opts dockertypes.ImagePullOptions) error { - const operation = "pull_image" - defer recordOperation(operation, time.Now()) - err := in.client.PullImage(imageID, auth, opts) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) RemoveImage(image string, opts dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDeleteResponseItem, error) { - const operation = "remove_image" - defer recordOperation(operation, time.Now()) - - imageDelete, err := in.client.RemoveImage(image, opts) - recordError(operation, err) - return imageDelete, err -} - -func (in instrumentedInterface) Logs(id string, opts dockertypes.ContainerLogsOptions, sopts StreamOptions) error { - const operation = "logs" - defer recordOperation(operation, time.Now()) - - err := in.client.Logs(id, opts, sopts) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) Version() (*dockertypes.Version, error) { - const operation = "version" - defer recordOperation(operation, time.Now()) - - out, err := in.client.Version() - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) Info() (*dockertypes.Info, error) { - const operation = "info" - defer recordOperation(operation, time.Now()) - - out, err := in.client.Info() - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) CreateExec(id string, opts dockertypes.ExecConfig) (*dockertypes.IDResponse, error) { - const operation = "create_exec" - defer recordOperation(operation, time.Now()) - - out, err := in.client.CreateExec(id, opts) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) StartExec(startExec string, opts dockertypes.ExecStartCheck, sopts StreamOptions) error { - const operation = "start_exec" - defer recordOperation(operation, time.Now()) - - err := in.client.StartExec(startExec, opts, sopts) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) InspectExec(id string) (*dockertypes.ContainerExecInspect, error) { - const operation = "inspect_exec" - defer recordOperation(operation, time.Now()) - - out, err := in.client.InspectExec(id) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) AttachToContainer(id string, opts dockertypes.ContainerAttachOptions, sopts StreamOptions) error { - const operation = "attach" - defer recordOperation(operation, time.Now()) - - err := in.client.AttachToContainer(id, opts, sopts) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) ImageHistory(id string) ([]dockerimagetypes.HistoryResponseItem, error) { - const operation = "image_history" - defer recordOperation(operation, time.Now()) - - out, err := in.client.ImageHistory(id) - recordError(operation, err) - return out, err -} - -func (in instrumentedInterface) ResizeExecTTY(id string, height, width uint) error { - const operation = "resize_exec" - defer recordOperation(operation, time.Now()) - - err := in.client.ResizeExecTTY(id, height, width) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) ResizeContainerTTY(id string, height, width uint) error { - const operation = "resize_container" - defer recordOperation(operation, time.Now()) - - err := in.client.ResizeContainerTTY(id, height, width) - recordError(operation, err) - return err -} - -func (in instrumentedInterface) GetContainerStats(id string) (*dockertypes.StatsJSON, error) { - const operation = "stats" - defer recordOperation(operation, time.Now()) - - out, err := in.client.GetContainerStats(id) - recordError(operation, err) - return out, err -} diff --git a/pkg/kubelet/dockershim/libdocker/kube_docker_client.go b/pkg/kubelet/dockershim/libdocker/kube_docker_client.go deleted file mode 100644 index 7df051f8174..00000000000 --- a/pkg/kubelet/dockershim/libdocker/kube_docker_client.go +++ /dev/null @@ -1,678 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package libdocker - -import ( - "bytes" - "context" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "regexp" - "sync" - "time" - - "k8s.io/klog/v2" - - dockertypes "github.com/docker/docker/api/types" - dockercontainer "github.com/docker/docker/api/types/container" - dockerimagetypes "github.com/docker/docker/api/types/image" - dockerapi "github.com/docker/docker/client" - dockermessage "github.com/docker/docker/pkg/jsonmessage" - dockerstdcopy "github.com/docker/docker/pkg/stdcopy" -) - -// kubeDockerClient is a wrapped layer of docker client for kubelet internal use. This layer is added to: -// 1) Redirect stream for exec and attach operations. -// 2) Wrap the context in this layer to make the Interface cleaner. -type kubeDockerClient struct { - // timeout is the timeout of short running docker operations. - timeout time.Duration - // If no pulling progress is made before imagePullProgressDeadline, the image pulling will be cancelled. - // Docker reports image progress for every 512kB block, so normally there shouldn't be too long interval - // between progress updates. - imagePullProgressDeadline time.Duration - client *dockerapi.Client -} - -// Make sure that kubeDockerClient implemented the Interface. -var _ Interface = &kubeDockerClient{} - -// There are 2 kinds of docker operations categorized by running time: -// * Long running operation: The long running operation could run for arbitrary long time, and the running time -// usually depends on some uncontrollable factors. These operations include: PullImage, Logs, StartExec, AttachToContainer. -// * Non-long running operation: Given the maximum load of the system, the non-long running operation should finish -// in expected and usually short time. These include all other operations. -// kubeDockerClient only applies timeout on non-long running operations. -const ( - // defaultTimeout is the default timeout of short running docker operations. - // Value is slightly offset from 2 minutes to make timeouts due to this - // constant recognizable. - defaultTimeout = 2*time.Minute - 1*time.Second - - // defaultShmSize is the default ShmSize to use (in bytes) if not specified. - defaultShmSize = int64(1024 * 1024 * 64) - - // defaultImagePullingProgressReportInterval is the default interval of image pulling progress reporting. - defaultImagePullingProgressReportInterval = 10 * time.Second -) - -// newKubeDockerClient creates an kubeDockerClient from an existing docker client. If requestTimeout is 0, -// defaultTimeout will be applied. -func newKubeDockerClient(dockerClient *dockerapi.Client, requestTimeout, imagePullProgressDeadline time.Duration) Interface { - if requestTimeout == 0 { - requestTimeout = defaultTimeout - } - - k := &kubeDockerClient{ - client: dockerClient, - timeout: requestTimeout, - imagePullProgressDeadline: imagePullProgressDeadline, - } - - // Notice that this assumes that docker is running before kubelet is started. - ctx, cancel := k.getTimeoutContext() - defer cancel() - dockerClient.NegotiateAPIVersion(ctx) - - return k -} - -func (d *kubeDockerClient) ListContainers(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - containers, err := d.client.ContainerList(ctx, options) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return containers, nil -} - -func (d *kubeDockerClient) InspectContainer(id string) (*dockertypes.ContainerJSON, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - containerJSON, err := d.client.ContainerInspect(ctx, id) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return &containerJSON, nil -} - -// InspectContainerWithSize is currently only used for Windows container stats -func (d *kubeDockerClient) InspectContainerWithSize(id string) (*dockertypes.ContainerJSON, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - // Inspects the container including the fields SizeRw and SizeRootFs. - containerJSON, _, err := d.client.ContainerInspectWithRaw(ctx, id, true) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return &containerJSON, nil -} - -func (d *kubeDockerClient) CreateContainer(opts dockertypes.ContainerCreateConfig) (*dockercontainer.ContainerCreateCreatedBody, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - // we provide an explicit default shm size as to not depend on docker daemon. - // TODO: evaluate exposing this as a knob in the API - if opts.HostConfig != nil && opts.HostConfig.ShmSize <= 0 { - opts.HostConfig.ShmSize = defaultShmSize - } - createResp, err := d.client.ContainerCreate(ctx, opts.Config, opts.HostConfig, opts.NetworkingConfig, nil, opts.Name) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return &createResp, nil -} - -func (d *kubeDockerClient) StartContainer(id string) error { - ctx, cancel := d.getTimeoutContext() - defer cancel() - err := d.client.ContainerStart(ctx, id, dockertypes.ContainerStartOptions{}) - if ctxErr := contextError(ctx); ctxErr != nil { - return ctxErr - } - return err -} - -// Stopping an already stopped container will not cause an error in dockerapi. -func (d *kubeDockerClient) StopContainer(id string, timeout time.Duration) error { - ctx, cancel := d.getCustomTimeoutContext(timeout) - defer cancel() - err := d.client.ContainerStop(ctx, id, &timeout) - if ctxErr := contextError(ctx); ctxErr != nil { - return ctxErr - } - return err -} - -func (d *kubeDockerClient) RemoveContainer(id string, opts dockertypes.ContainerRemoveOptions) error { - ctx, cancel := d.getTimeoutContext() - defer cancel() - err := d.client.ContainerRemove(ctx, id, opts) - if ctxErr := contextError(ctx); ctxErr != nil { - return ctxErr - } - return err -} - -func (d *kubeDockerClient) UpdateContainerResources(id string, updateConfig dockercontainer.UpdateConfig) error { - ctx, cancel := d.getTimeoutContext() - defer cancel() - _, err := d.client.ContainerUpdate(ctx, id, updateConfig) - if ctxErr := contextError(ctx); ctxErr != nil { - return ctxErr - } - return err -} - -func (d *kubeDockerClient) inspectImageRaw(ref string) (*dockertypes.ImageInspect, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - resp, _, err := d.client.ImageInspectWithRaw(ctx, ref) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - if dockerapi.IsErrNotFound(err) { - err = ImageNotFoundError{ID: ref} - } - return nil, err - } - - return &resp, nil -} - -func (d *kubeDockerClient) InspectImageByID(imageID string) (*dockertypes.ImageInspect, error) { - resp, err := d.inspectImageRaw(imageID) - if err != nil { - return nil, err - } - - if !matchImageIDOnly(*resp, imageID) { - return nil, ImageNotFoundError{ID: imageID} - } - return resp, nil -} - -func (d *kubeDockerClient) InspectImageByRef(imageRef string) (*dockertypes.ImageInspect, error) { - resp, err := d.inspectImageRaw(imageRef) - if err != nil { - return nil, err - } - - if !matchImageTagOrSHA(*resp, imageRef) { - return nil, ImageNotFoundError{ID: imageRef} - } - return resp, nil -} - -func (d *kubeDockerClient) ImageHistory(id string) ([]dockerimagetypes.HistoryResponseItem, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - resp, err := d.client.ImageHistory(ctx, id) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - return resp, err -} - -func (d *kubeDockerClient) ListImages(opts dockertypes.ImageListOptions) ([]dockertypes.ImageSummary, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - images, err := d.client.ImageList(ctx, opts) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return images, nil -} - -func base64EncodeAuth(auth dockertypes.AuthConfig) (string, error) { - var buf bytes.Buffer - if err := json.NewEncoder(&buf).Encode(auth); err != nil { - return "", err - } - return base64.URLEncoding.EncodeToString(buf.Bytes()), nil -} - -// progress is a wrapper of dockermessage.JSONMessage with a lock protecting it. -type progress struct { - sync.RWMutex - // message stores the latest docker json message. - message *dockermessage.JSONMessage - // timestamp of the latest update. - timestamp time.Time -} - -func newProgress() *progress { - return &progress{timestamp: time.Now()} -} - -func (p *progress) set(msg *dockermessage.JSONMessage) { - p.Lock() - defer p.Unlock() - p.message = msg - p.timestamp = time.Now() -} - -func (p *progress) get() (string, time.Time) { - p.RLock() - defer p.RUnlock() - if p.message == nil { - return "No progress", p.timestamp - } - // The following code is based on JSONMessage.Display - var prefix string - if p.message.ID != "" { - prefix = fmt.Sprintf("%s: ", p.message.ID) - } - if p.message.Progress == nil { - return fmt.Sprintf("%s%s", prefix, p.message.Status), p.timestamp - } - return fmt.Sprintf("%s%s %s", prefix, p.message.Status, p.message.Progress.String()), p.timestamp -} - -// progressReporter keeps the newest image pulling progress and periodically report the newest progress. -type progressReporter struct { - *progress - image string - cancel context.CancelFunc - stopCh chan struct{} - imagePullProgressDeadline time.Duration -} - -// newProgressReporter creates a new progressReporter for specific image with specified reporting interval -func newProgressReporter(image string, cancel context.CancelFunc, imagePullProgressDeadline time.Duration) *progressReporter { - return &progressReporter{ - progress: newProgress(), - image: image, - cancel: cancel, - stopCh: make(chan struct{}), - imagePullProgressDeadline: imagePullProgressDeadline, - } -} - -// start starts the progressReporter -func (p *progressReporter) start() { - go func() { - ticker := time.NewTicker(defaultImagePullingProgressReportInterval) - defer ticker.Stop() - for { - // TODO(random-liu): Report as events. - select { - case <-ticker.C: - progress, timestamp := p.progress.get() - // If there is no progress for p.imagePullProgressDeadline, cancel the operation. - if time.Since(timestamp) > p.imagePullProgressDeadline { - klog.ErrorS(nil, "Cancel pulling image because of exceed image pull deadline, record latest progress", "image", p.image, "deadline", p.imagePullProgressDeadline, "progress", progress) - p.cancel() - return - } - klog.V(2).InfoS("Pulling image", "image", p.image, "progress", progress) - case <-p.stopCh: - progress, _ := p.progress.get() - klog.V(2).InfoS("Stop pulling image", "image", p.image, "progress", progress) - return - } - } - }() -} - -// stop stops the progressReporter -func (p *progressReporter) stop() { - close(p.stopCh) -} - -func (d *kubeDockerClient) PullImage(image string, auth dockertypes.AuthConfig, opts dockertypes.ImagePullOptions) error { - // RegistryAuth is the base64 encoded credentials for the registry - base64Auth, err := base64EncodeAuth(auth) - if err != nil { - return err - } - opts.RegistryAuth = base64Auth - ctx, cancel := d.getCancelableContext() - defer cancel() - resp, err := d.client.ImagePull(ctx, image, opts) - if err != nil { - return err - } - defer resp.Close() - reporter := newProgressReporter(image, cancel, d.imagePullProgressDeadline) - reporter.start() - defer reporter.stop() - decoder := json.NewDecoder(resp) - for { - var msg dockermessage.JSONMessage - err := decoder.Decode(&msg) - if err == io.EOF { - break - } - if err != nil { - return err - } - if msg.Error != nil { - return msg.Error - } - reporter.set(&msg) - } - return nil -} - -func (d *kubeDockerClient) RemoveImage(image string, opts dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDeleteResponseItem, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - resp, err := d.client.ImageRemove(ctx, image, opts) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if dockerapi.IsErrNotFound(err) { - return nil, ImageNotFoundError{ID: image} - } - return resp, err -} - -func (d *kubeDockerClient) Logs(id string, opts dockertypes.ContainerLogsOptions, sopts StreamOptions) error { - ctx, cancel := d.getCancelableContext() - defer cancel() - resp, err := d.client.ContainerLogs(ctx, id, opts) - if ctxErr := contextError(ctx); ctxErr != nil { - return ctxErr - } - if err != nil { - return err - } - defer resp.Close() - return d.redirectResponseToOutputStream(sopts.RawTerminal, sopts.OutputStream, sopts.ErrorStream, resp) -} - -func (d *kubeDockerClient) Version() (*dockertypes.Version, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - resp, err := d.client.ServerVersion(ctx) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return &resp, nil -} - -func (d *kubeDockerClient) Info() (*dockertypes.Info, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - resp, err := d.client.Info(ctx) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return &resp, nil -} - -// TODO(random-liu): Add unit test for exec and attach functions, just like what go-dockerclient did. -func (d *kubeDockerClient) CreateExec(id string, opts dockertypes.ExecConfig) (*dockertypes.IDResponse, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - resp, err := d.client.ContainerExecCreate(ctx, id, opts) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return &resp, nil -} - -func (d *kubeDockerClient) StartExec(startExec string, opts dockertypes.ExecStartCheck, sopts StreamOptions) error { - ctx, cancel := d.getCancelableContext() - defer cancel() - if opts.Detach { - err := d.client.ContainerExecStart(ctx, startExec, opts) - if ctxErr := contextError(ctx); ctxErr != nil { - return ctxErr - } - return err - } - resp, err := d.client.ContainerExecAttach(ctx, startExec, dockertypes.ExecStartCheck{ - Detach: opts.Detach, - Tty: opts.Tty, - }) - if ctxErr := contextError(ctx); ctxErr != nil { - return ctxErr - } - if err != nil { - return err - } - defer resp.Close() - - if sopts.ExecStarted != nil { - // Send a message to the channel indicating that the exec has started. This is needed so - // interactive execs can handle resizing correctly - the request to resize the TTY has to happen - // after the call to d.client.ContainerExecAttach, and because d.holdHijackedConnection below - // blocks, we use sopts.ExecStarted to signal the caller that it's ok to resize. - sopts.ExecStarted <- struct{}{} - } - - return d.holdHijackedConnection(sopts.RawTerminal || opts.Tty, sopts.InputStream, sopts.OutputStream, sopts.ErrorStream, resp) -} - -func (d *kubeDockerClient) InspectExec(id string) (*dockertypes.ContainerExecInspect, error) { - ctx, cancel := d.getTimeoutContext() - defer cancel() - resp, err := d.client.ContainerExecInspect(ctx, id) - if ctxErr := contextError(ctx); ctxErr != nil { - return nil, ctxErr - } - if err != nil { - return nil, err - } - return &resp, nil -} - -func (d *kubeDockerClient) AttachToContainer(id string, opts dockertypes.ContainerAttachOptions, sopts StreamOptions) error { - ctx, cancel := d.getCancelableContext() - defer cancel() - resp, err := d.client.ContainerAttach(ctx, id, opts) - if ctxErr := contextError(ctx); ctxErr != nil { - return ctxErr - } - if err != nil { - return err - } - defer resp.Close() - return d.holdHijackedConnection(sopts.RawTerminal, sopts.InputStream, sopts.OutputStream, sopts.ErrorStream, resp) -} - -func (d *kubeDockerClient) ResizeExecTTY(id string, height, width uint) error { - ctx, cancel := d.getCancelableContext() - defer cancel() - return d.client.ContainerExecResize(ctx, id, dockertypes.ResizeOptions{ - Height: height, - Width: width, - }) -} - -func (d *kubeDockerClient) ResizeContainerTTY(id string, height, width uint) error { - ctx, cancel := d.getCancelableContext() - defer cancel() - return d.client.ContainerResize(ctx, id, dockertypes.ResizeOptions{ - Height: height, - Width: width, - }) -} - -// GetContainerStats is currently only used for Windows container stats -func (d *kubeDockerClient) GetContainerStats(id string) (*dockertypes.StatsJSON, error) { - ctx, cancel := d.getCancelableContext() - defer cancel() - - response, err := d.client.ContainerStats(ctx, id, false) - if err != nil { - return nil, err - } - - dec := json.NewDecoder(response.Body) - var stats dockertypes.StatsJSON - err = dec.Decode(&stats) - if err != nil { - return nil, err - } - - defer response.Body.Close() - return &stats, nil -} - -// redirectResponseToOutputStream redirect the response stream to stdout and stderr. When tty is true, all stream will -// only be redirected to stdout. -func (d *kubeDockerClient) redirectResponseToOutputStream(tty bool, outputStream, errorStream io.Writer, resp io.Reader) error { - if outputStream == nil { - outputStream = ioutil.Discard - } - if errorStream == nil { - errorStream = ioutil.Discard - } - var err error - if tty { - _, err = io.Copy(outputStream, resp) - } else { - _, err = dockerstdcopy.StdCopy(outputStream, errorStream, resp) - } - return err -} - -// holdHijackedConnection hold the HijackedResponse, redirect the inputStream to the connection, and redirect the response -// stream to stdout and stderr. NOTE: If needed, we could also add context in this function. -func (d *kubeDockerClient) holdHijackedConnection(tty bool, inputStream io.Reader, outputStream, errorStream io.Writer, resp dockertypes.HijackedResponse) error { - receiveStdout := make(chan error) - if outputStream != nil || errorStream != nil { - go func() { - receiveStdout <- d.redirectResponseToOutputStream(tty, outputStream, errorStream, resp.Reader) - }() - } - - stdinDone := make(chan struct{}) - go func() { - if inputStream != nil { - io.Copy(resp.Conn, inputStream) - } - resp.CloseWrite() - close(stdinDone) - }() - - select { - case err := <-receiveStdout: - return err - case <-stdinDone: - if outputStream != nil || errorStream != nil { - return <-receiveStdout - } - } - return nil -} - -// getCancelableContext returns a new cancelable context. For long running requests without timeout, we use cancelable -// context to avoid potential resource leak, although the current implementation shouldn't leak resource. -func (d *kubeDockerClient) getCancelableContext() (context.Context, context.CancelFunc) { - return context.WithCancel(context.Background()) -} - -// getTimeoutContext returns a new context with default request timeout -func (d *kubeDockerClient) getTimeoutContext() (context.Context, context.CancelFunc) { - return context.WithTimeout(context.Background(), d.timeout) -} - -// getCustomTimeoutContext returns a new context with a specific request timeout -func (d *kubeDockerClient) getCustomTimeoutContext(timeout time.Duration) (context.Context, context.CancelFunc) { - // Pick the larger of the two - if d.timeout > timeout { - timeout = d.timeout - } - return context.WithTimeout(context.Background(), timeout) -} - -// contextError checks the context, and returns error if the context is timeout. -func contextError(ctx context.Context) error { - if ctx.Err() == context.DeadlineExceeded { - return operationTimeout{err: ctx.Err()} - } - return ctx.Err() -} - -// StreamOptions are the options used to configure the stream redirection -type StreamOptions struct { - RawTerminal bool - InputStream io.Reader - OutputStream io.Writer - ErrorStream io.Writer - ExecStarted chan struct{} -} - -// operationTimeout is the error returned when the docker operations are timeout. -type operationTimeout struct { - err error -} - -func (e operationTimeout) Error() string { - return fmt.Sprintf("operation timeout: %v", e.err) -} - -// containerNotFoundErrorRegx is the regexp of container not found error message. -var containerNotFoundErrorRegx = regexp.MustCompile(`No such container: [0-9a-z]+`) - -// IsContainerNotFoundError checks whether the error is container not found error. -func IsContainerNotFoundError(err error) bool { - return containerNotFoundErrorRegx.MatchString(err.Error()) -} - -// ImageNotFoundError is the error returned by InspectImage when image not found. -// Expose this to inject error in dockershim for testing. -type ImageNotFoundError struct { - ID string -} - -func (e ImageNotFoundError) Error() string { - return fmt.Sprintf("no such image: %q", e.ID) -} - -// IsImageNotFoundError checks whether the error is image not found error. This is exposed -// to share with dockershim. -func IsImageNotFoundError(err error) bool { - _, ok := err.(ImageNotFoundError) - return ok -} diff --git a/pkg/kubelet/dockershim/libdocker/kube_docker_client_test.go b/pkg/kubelet/dockershim/libdocker/kube_docker_client_test.go deleted file mode 100644 index 42dab7a7d84..00000000000 --- a/pkg/kubelet/dockershim/libdocker/kube_docker_client_test.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package libdocker - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestIsContainerNotFoundError(t *testing.T) { - // Expected error message from docker. - containerNotFoundError := fmt.Errorf("Error response from daemon: No such container: 96e914f31579e44fe49b239266385330a9b2125abeb9254badd9fca74580c95a") - otherError := fmt.Errorf("Error response from daemon: Other errors") - - assert.True(t, IsContainerNotFoundError(containerNotFoundError)) - assert.False(t, IsContainerNotFoundError(otherError)) -} diff --git a/pkg/kubelet/dockershim/libdocker/testing/mock_client.go b/pkg/kubelet/dockershim/libdocker/testing/mock_client.go deleted file mode 100644 index 72e7aba7fc6..00000000000 --- a/pkg/kubelet/dockershim/libdocker/testing/mock_client.go +++ /dev/null @@ -1,407 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright The Kubernetes 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. -*/ - -// Code generated by MockGen. DO NOT EDIT. -// Source: client.go - -// Package testing is a generated GoMock package. -package testing - -import ( - types "github.com/docker/docker/api/types" - container "github.com/docker/docker/api/types/container" - image "github.com/docker/docker/api/types/image" - gomock "github.com/golang/mock/gomock" - libdocker "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" - reflect "reflect" - time "time" -) - -// MockInterface is a mock of Interface interface -type MockInterface struct { - ctrl *gomock.Controller - recorder *MockInterfaceMockRecorder -} - -// MockInterfaceMockRecorder is the mock recorder for MockInterface -type MockInterfaceMockRecorder struct { - mock *MockInterface -} - -// NewMockInterface creates a new mock instance -func NewMockInterface(ctrl *gomock.Controller) *MockInterface { - mock := &MockInterface{ctrl: ctrl} - mock.recorder = &MockInterfaceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { - return m.recorder -} - -// ListContainers mocks base method -func (m *MockInterface) ListContainers(options types.ContainerListOptions) ([]types.Container, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ListContainers", options) - ret0, _ := ret[0].([]types.Container) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ListContainers indicates an expected call of ListContainers -func (mr *MockInterfaceMockRecorder) ListContainers(options interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListContainers", reflect.TypeOf((*MockInterface)(nil).ListContainers), options) -} - -// InspectContainer mocks base method -func (m *MockInterface) InspectContainer(id string) (*types.ContainerJSON, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InspectContainer", id) - ret0, _ := ret[0].(*types.ContainerJSON) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// InspectContainer indicates an expected call of InspectContainer -func (mr *MockInterfaceMockRecorder) InspectContainer(id interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InspectContainer", reflect.TypeOf((*MockInterface)(nil).InspectContainer), id) -} - -// InspectContainerWithSize mocks base method -func (m *MockInterface) InspectContainerWithSize(id string) (*types.ContainerJSON, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InspectContainerWithSize", id) - ret0, _ := ret[0].(*types.ContainerJSON) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// InspectContainerWithSize indicates an expected call of InspectContainerWithSize -func (mr *MockInterfaceMockRecorder) InspectContainerWithSize(id interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InspectContainerWithSize", reflect.TypeOf((*MockInterface)(nil).InspectContainerWithSize), id) -} - -// CreateContainer mocks base method -func (m *MockInterface) CreateContainer(arg0 types.ContainerCreateConfig) (*container.ContainerCreateCreatedBody, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateContainer", arg0) - ret0, _ := ret[0].(*container.ContainerCreateCreatedBody) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateContainer indicates an expected call of CreateContainer -func (mr *MockInterfaceMockRecorder) CreateContainer(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateContainer", reflect.TypeOf((*MockInterface)(nil).CreateContainer), arg0) -} - -// StartContainer mocks base method -func (m *MockInterface) StartContainer(id string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StartContainer", id) - ret0, _ := ret[0].(error) - return ret0 -} - -// StartContainer indicates an expected call of StartContainer -func (mr *MockInterfaceMockRecorder) StartContainer(id interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartContainer", reflect.TypeOf((*MockInterface)(nil).StartContainer), id) -} - -// StopContainer mocks base method -func (m *MockInterface) StopContainer(id string, timeout time.Duration) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StopContainer", id, timeout) - ret0, _ := ret[0].(error) - return ret0 -} - -// StopContainer indicates an expected call of StopContainer -func (mr *MockInterfaceMockRecorder) StopContainer(id, timeout interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StopContainer", reflect.TypeOf((*MockInterface)(nil).StopContainer), id, timeout) -} - -// UpdateContainerResources mocks base method -func (m *MockInterface) UpdateContainerResources(id string, updateConfig container.UpdateConfig) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateContainerResources", id, updateConfig) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateContainerResources indicates an expected call of UpdateContainerResources -func (mr *MockInterfaceMockRecorder) UpdateContainerResources(id, updateConfig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateContainerResources", reflect.TypeOf((*MockInterface)(nil).UpdateContainerResources), id, updateConfig) -} - -// RemoveContainer mocks base method -func (m *MockInterface) RemoveContainer(id string, opts types.ContainerRemoveOptions) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RemoveContainer", id, opts) - ret0, _ := ret[0].(error) - return ret0 -} - -// RemoveContainer indicates an expected call of RemoveContainer -func (mr *MockInterfaceMockRecorder) RemoveContainer(id, opts interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveContainer", reflect.TypeOf((*MockInterface)(nil).RemoveContainer), id, opts) -} - -// InspectImageByRef mocks base method -func (m *MockInterface) InspectImageByRef(imageRef string) (*types.ImageInspect, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InspectImageByRef", imageRef) - ret0, _ := ret[0].(*types.ImageInspect) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// InspectImageByRef indicates an expected call of InspectImageByRef -func (mr *MockInterfaceMockRecorder) InspectImageByRef(imageRef interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InspectImageByRef", reflect.TypeOf((*MockInterface)(nil).InspectImageByRef), imageRef) -} - -// InspectImageByID mocks base method -func (m *MockInterface) InspectImageByID(imageID string) (*types.ImageInspect, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InspectImageByID", imageID) - ret0, _ := ret[0].(*types.ImageInspect) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// InspectImageByID indicates an expected call of InspectImageByID -func (mr *MockInterfaceMockRecorder) InspectImageByID(imageID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InspectImageByID", reflect.TypeOf((*MockInterface)(nil).InspectImageByID), imageID) -} - -// ListImages mocks base method -func (m *MockInterface) ListImages(opts types.ImageListOptions) ([]types.ImageSummary, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ListImages", opts) - ret0, _ := ret[0].([]types.ImageSummary) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ListImages indicates an expected call of ListImages -func (mr *MockInterfaceMockRecorder) ListImages(opts interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListImages", reflect.TypeOf((*MockInterface)(nil).ListImages), opts) -} - -// PullImage mocks base method -func (m *MockInterface) PullImage(image string, auth types.AuthConfig, opts types.ImagePullOptions) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PullImage", image, auth, opts) - ret0, _ := ret[0].(error) - return ret0 -} - -// PullImage indicates an expected call of PullImage -func (mr *MockInterfaceMockRecorder) PullImage(image, auth, opts interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PullImage", reflect.TypeOf((*MockInterface)(nil).PullImage), image, auth, opts) -} - -// RemoveImage mocks base method -func (m *MockInterface) RemoveImage(image string, opts types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RemoveImage", image, opts) - ret0, _ := ret[0].([]types.ImageDeleteResponseItem) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RemoveImage indicates an expected call of RemoveImage -func (mr *MockInterfaceMockRecorder) RemoveImage(image, opts interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveImage", reflect.TypeOf((*MockInterface)(nil).RemoveImage), image, opts) -} - -// ImageHistory mocks base method -func (m *MockInterface) ImageHistory(id string) ([]image.HistoryResponseItem, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ImageHistory", id) - ret0, _ := ret[0].([]image.HistoryResponseItem) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ImageHistory indicates an expected call of ImageHistory -func (mr *MockInterfaceMockRecorder) ImageHistory(id interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageHistory", reflect.TypeOf((*MockInterface)(nil).ImageHistory), id) -} - -// Logs mocks base method -func (m *MockInterface) Logs(arg0 string, arg1 types.ContainerLogsOptions, arg2 libdocker.StreamOptions) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Logs", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// Logs indicates an expected call of Logs -func (mr *MockInterfaceMockRecorder) Logs(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Logs", reflect.TypeOf((*MockInterface)(nil).Logs), arg0, arg1, arg2) -} - -// Version mocks base method -func (m *MockInterface) Version() (*types.Version, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Version") - ret0, _ := ret[0].(*types.Version) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Version indicates an expected call of Version -func (mr *MockInterfaceMockRecorder) Version() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Version", reflect.TypeOf((*MockInterface)(nil).Version)) -} - -// Info mocks base method -func (m *MockInterface) Info() (*types.Info, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Info") - ret0, _ := ret[0].(*types.Info) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Info indicates an expected call of Info -func (mr *MockInterfaceMockRecorder) Info() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockInterface)(nil).Info)) -} - -// CreateExec mocks base method -func (m *MockInterface) CreateExec(arg0 string, arg1 types.ExecConfig) (*types.IDResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateExec", arg0, arg1) - ret0, _ := ret[0].(*types.IDResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateExec indicates an expected call of CreateExec -func (mr *MockInterfaceMockRecorder) CreateExec(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateExec", reflect.TypeOf((*MockInterface)(nil).CreateExec), arg0, arg1) -} - -// StartExec mocks base method -func (m *MockInterface) StartExec(arg0 string, arg1 types.ExecStartCheck, arg2 libdocker.StreamOptions) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StartExec", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// StartExec indicates an expected call of StartExec -func (mr *MockInterfaceMockRecorder) StartExec(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartExec", reflect.TypeOf((*MockInterface)(nil).StartExec), arg0, arg1, arg2) -} - -// InspectExec mocks base method -func (m *MockInterface) InspectExec(id string) (*types.ContainerExecInspect, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InspectExec", id) - ret0, _ := ret[0].(*types.ContainerExecInspect) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// InspectExec indicates an expected call of InspectExec -func (mr *MockInterfaceMockRecorder) InspectExec(id interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InspectExec", reflect.TypeOf((*MockInterface)(nil).InspectExec), id) -} - -// AttachToContainer mocks base method -func (m *MockInterface) AttachToContainer(arg0 string, arg1 types.ContainerAttachOptions, arg2 libdocker.StreamOptions) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AttachToContainer", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// AttachToContainer indicates an expected call of AttachToContainer -func (mr *MockInterfaceMockRecorder) AttachToContainer(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AttachToContainer", reflect.TypeOf((*MockInterface)(nil).AttachToContainer), arg0, arg1, arg2) -} - -// ResizeContainerTTY mocks base method -func (m *MockInterface) ResizeContainerTTY(id string, height, width uint) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ResizeContainerTTY", id, height, width) - ret0, _ := ret[0].(error) - return ret0 -} - -// ResizeContainerTTY indicates an expected call of ResizeContainerTTY -func (mr *MockInterfaceMockRecorder) ResizeContainerTTY(id, height, width interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResizeContainerTTY", reflect.TypeOf((*MockInterface)(nil).ResizeContainerTTY), id, height, width) -} - -// ResizeExecTTY mocks base method -func (m *MockInterface) ResizeExecTTY(id string, height, width uint) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ResizeExecTTY", id, height, width) - ret0, _ := ret[0].(error) - return ret0 -} - -// ResizeExecTTY indicates an expected call of ResizeExecTTY -func (mr *MockInterfaceMockRecorder) ResizeExecTTY(id, height, width interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResizeExecTTY", reflect.TypeOf((*MockInterface)(nil).ResizeExecTTY), id, height, width) -} - -// GetContainerStats mocks base method -func (m *MockInterface) GetContainerStats(id string) (*types.StatsJSON, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetContainerStats", id) - ret0, _ := ret[0].(*types.StatsJSON) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetContainerStats indicates an expected call of GetContainerStats -func (mr *MockInterfaceMockRecorder) GetContainerStats(id interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContainerStats", reflect.TypeOf((*MockInterface)(nil).GetContainerStats), id) -} diff --git a/pkg/kubelet/dockershim/metrics/metrics.go b/pkg/kubelet/dockershim/metrics/metrics.go deleted file mode 100644 index be8d65b83ea..00000000000 --- a/pkg/kubelet/dockershim/metrics/metrics.go +++ /dev/null @@ -1,105 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package metrics - -import ( - "sync" - "time" - - "k8s.io/component-base/metrics" - "k8s.io/component-base/metrics/legacyregistry" -) - -const ( - // DockerOperationsKey is the key for docker operation metrics. - DockerOperationsKey = "docker_operations_total" - // DockerOperationsLatencyKey is the key for the operation latency metrics. - DockerOperationsLatencyKey = "docker_operations_duration_seconds" - // DockerOperationsErrorsKey is the key for the operation error metrics. - DockerOperationsErrorsKey = "docker_operations_errors_total" - // DockerOperationsTimeoutKey is the key for the operation timeout metrics. - DockerOperationsTimeoutKey = "docker_operations_timeout_total" - - // Keep the "kubelet" subsystem for backward compatibility. - kubeletSubsystem = "kubelet" -) - -var ( - // DockerOperationsLatency collects operation latency numbers by operation - // type. - DockerOperationsLatency = metrics.NewHistogramVec( - &metrics.HistogramOpts{ - Subsystem: kubeletSubsystem, - Name: DockerOperationsLatencyKey, - Help: "Latency in seconds of Docker operations. Broken down by operation type.", - Buckets: metrics.DefBuckets, - StabilityLevel: metrics.ALPHA, - }, - []string{"operation_type"}, - ) - // DockerOperations collects operation counts by operation type. - DockerOperations = metrics.NewCounterVec( - &metrics.CounterOpts{ - Subsystem: kubeletSubsystem, - Name: DockerOperationsKey, - Help: "Cumulative number of Docker operations by operation type.", - StabilityLevel: metrics.ALPHA, - }, - []string{"operation_type"}, - ) - // DockerOperationsErrors collects operation errors by operation - // type. - DockerOperationsErrors = metrics.NewCounterVec( - &metrics.CounterOpts{ - Subsystem: kubeletSubsystem, - Name: DockerOperationsErrorsKey, - Help: "Cumulative number of Docker operation errors by operation type.", - StabilityLevel: metrics.ALPHA, - }, - []string{"operation_type"}, - ) - // DockerOperationsTimeout collects operation timeouts by operation type. - DockerOperationsTimeout = metrics.NewCounterVec( - &metrics.CounterOpts{ - Subsystem: kubeletSubsystem, - Name: DockerOperationsTimeoutKey, - Help: "Cumulative number of Docker operation timeout by operation type.", - StabilityLevel: metrics.ALPHA, - }, - []string{"operation_type"}, - ) -) - -var registerMetrics sync.Once - -// Register all metrics. -func Register() { - registerMetrics.Do(func() { - legacyregistry.MustRegister(DockerOperationsLatency) - legacyregistry.MustRegister(DockerOperations) - legacyregistry.MustRegister(DockerOperationsErrors) - legacyregistry.MustRegister(DockerOperationsTimeout) - }) -} - -// SinceInSeconds gets the time since the specified start in seconds. -func SinceInSeconds(start time.Time) float64 { - return time.Since(start).Seconds() -} diff --git a/pkg/kubelet/dockershim/naming.go b/pkg/kubelet/dockershim/naming.go deleted file mode 100644 index faf35b6bf68..00000000000 --- a/pkg/kubelet/dockershim/naming.go +++ /dev/null @@ -1,152 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - "math/rand" - "strconv" - "strings" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/leaky" -) - -// Container "names" are implementation details that do not concern -// kubelet/CRI. This CRI shim uses names to fulfill the CRI requirement to -// make sandbox/container creation idempotent. CRI states that there can -// only exist one sandbox/container with the given metadata. To enforce this, -// this shim constructs a name using the fields in the metadata so that -// docker will reject the creation request if the name already exists. -// -// Note that changes to naming will likely break the backward compatibility. -// Code must be added to ensure the shim knows how to recognize and extract -// information the older containers. -// -// TODO: Add code to handle backward compatibility, i.e., making sure we can -// recognize older containers and extract information from their names if -// necessary. - -const ( - // kubePrefix is used to identify the containers/sandboxes on the node managed by kubelet - kubePrefix = "k8s" - // sandboxContainerName is a string to include in the docker container so - // that users can easily identify the sandboxes. - sandboxContainerName = leaky.PodInfraContainerName - // Delimiter used to construct docker container names. - nameDelimiter = "_" - // DockerImageIDPrefix is the prefix of image id in container status. - DockerImageIDPrefix = "docker://" - // DockerPullableImageIDPrefix is the prefix of pullable image id in container status. - DockerPullableImageIDPrefix = "docker-pullable://" -) - -func makeSandboxName(s *runtimeapi.PodSandboxConfig) string { - return strings.Join([]string{ - kubePrefix, // 0 - sandboxContainerName, // 1 - s.Metadata.Name, // 2 - s.Metadata.Namespace, // 3 - s.Metadata.Uid, // 4 - fmt.Sprintf("%d", s.Metadata.Attempt), // 5 - }, nameDelimiter) -} - -func makeContainerName(s *runtimeapi.PodSandboxConfig, c *runtimeapi.ContainerConfig) string { - return strings.Join([]string{ - kubePrefix, // 0 - c.Metadata.Name, // 1: - s.Metadata.Name, // 2: sandbox name - s.Metadata.Namespace, // 3: sandbox namesapce - s.Metadata.Uid, // 4 sandbox uid - fmt.Sprintf("%d", c.Metadata.Attempt), // 5 - }, nameDelimiter) -} - -// randomizeName randomizes the container name. This should only be used when we hit the -// docker container name conflict bug. -func randomizeName(name string) string { - return strings.Join([]string{ - name, - fmt.Sprintf("%08x", rand.Uint32()), - }, nameDelimiter) -} - -func parseUint32(s string) (uint32, error) { - n, err := strconv.ParseUint(s, 10, 32) - if err != nil { - return 0, err - } - return uint32(n), nil -} - -// TODO: Evaluate whether we should rely on labels completely. -func parseSandboxName(name string) (*runtimeapi.PodSandboxMetadata, error) { - // Docker adds a "/" prefix to names. so trim it. - name = strings.TrimPrefix(name, "/") - - parts := strings.Split(name, nameDelimiter) - // Tolerate the random suffix. - // TODO(random-liu): Remove 7 field case when docker 1.11 is deprecated. - if len(parts) != 6 && len(parts) != 7 { - return nil, fmt.Errorf("failed to parse the sandbox name: %q", name) - } - if parts[0] != kubePrefix { - return nil, fmt.Errorf("container is not managed by kubernetes: %q", name) - } - - attempt, err := parseUint32(parts[5]) - if err != nil { - return nil, fmt.Errorf("failed to parse the sandbox name %q: %v", name, err) - } - - return &runtimeapi.PodSandboxMetadata{ - Name: parts[2], - Namespace: parts[3], - Uid: parts[4], - Attempt: attempt, - }, nil -} - -// TODO: Evaluate whether we should rely on labels completely. -func parseContainerName(name string) (*runtimeapi.ContainerMetadata, error) { - // Docker adds a "/" prefix to names. so trim it. - name = strings.TrimPrefix(name, "/") - - parts := strings.Split(name, nameDelimiter) - // Tolerate the random suffix. - // TODO(random-liu): Remove 7 field case when docker 1.11 is deprecated. - if len(parts) != 6 && len(parts) != 7 { - return nil, fmt.Errorf("failed to parse the container name: %q", name) - } - if parts[0] != kubePrefix { - return nil, fmt.Errorf("container is not managed by kubernetes: %q", name) - } - - attempt, err := parseUint32(parts[5]) - if err != nil { - return nil, fmt.Errorf("failed to parse the container name %q: %v", name, err) - } - - return &runtimeapi.ContainerMetadata{ - Name: parts[1], - Attempt: attempt, - }, nil -} diff --git a/pkg/kubelet/dockershim/naming_test.go b/pkg/kubelet/dockershim/naming_test.go deleted file mode 100644 index 16c3f6b7ad0..00000000000 --- a/pkg/kubelet/dockershim/naming_test.go +++ /dev/null @@ -1,109 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -func TestSandboxNameRoundTrip(t *testing.T) { - config := makeSandboxConfig("foo", "bar", "iamuid", 3) - actualName := makeSandboxName(config) - assert.Equal(t, "k8s_POD_foo_bar_iamuid_3", actualName) - - actualMetadata, err := parseSandboxName(actualName) - assert.NoError(t, err) - assert.Equal(t, config.Metadata, actualMetadata) -} - -func TestNonParsableSandboxNames(t *testing.T) { - // All names must start with the kubernetes prefix "k8s". - _, err := parseSandboxName("owner_POD_foo_bar_iamuid_4") - assert.Error(t, err) - - // All names must contain exactly 6 parts. - _, err = parseSandboxName("k8s_POD_dummy_foo_bar_iamuid_4") - assert.Error(t, err) - _, err = parseSandboxName("k8s_foo_bar_iamuid_4") - assert.Error(t, err) - - // Should be able to parse attempt number. - _, err = parseSandboxName("k8s_POD_foo_bar_iamuid_notanumber") - assert.Error(t, err) -} - -func TestContainerNameRoundTrip(t *testing.T) { - sConfig := makeSandboxConfig("foo", "bar", "iamuid", 3) - name, attempt := "pause", uint32(5) - config := &runtimeapi.ContainerConfig{ - Metadata: &runtimeapi.ContainerMetadata{ - Name: name, - Attempt: attempt, - }, - } - actualName := makeContainerName(sConfig, config) - assert.Equal(t, "k8s_pause_foo_bar_iamuid_5", actualName) - - actualMetadata, err := parseContainerName(actualName) - assert.NoError(t, err) - assert.Equal(t, config.Metadata, actualMetadata) -} - -func TestNonParsableContainerNames(t *testing.T) { - // All names must start with the kubernetes prefix "k8s". - _, err := parseContainerName("owner_frontend_foo_bar_iamuid_4") - assert.Error(t, err) - - // All names must contain exactly 6 parts. - _, err = parseContainerName("k8s_frontend_dummy_foo_bar_iamuid_4") - assert.Error(t, err) - _, err = parseContainerName("k8s_foo_bar_iamuid_4") - assert.Error(t, err) - - // Should be able to parse attempt number. - _, err = parseContainerName("k8s_frontend_foo_bar_iamuid_notanumber") - assert.Error(t, err) -} - -func TestParseRandomizedNames(t *testing.T) { - // Test randomized sandbox name. - sConfig := makeSandboxConfig("foo", "bar", "iamuid", 3) - sActualName := randomizeName(makeSandboxName(sConfig)) - sActualMetadata, err := parseSandboxName(sActualName) - assert.NoError(t, err) - assert.Equal(t, sConfig.Metadata, sActualMetadata) - - // Test randomized container name. - name, attempt := "pause", uint32(5) - config := &runtimeapi.ContainerConfig{ - Metadata: &runtimeapi.ContainerMetadata{ - Name: name, - Attempt: attempt, - }, - } - actualName := randomizeName(makeContainerName(sConfig, config)) - actualMetadata, err := parseContainerName(actualName) - assert.NoError(t, err) - assert.Equal(t, config.Metadata, actualMetadata) -} diff --git a/pkg/kubelet/dockershim/network/OWNERS b/pkg/kubelet/dockershim/network/OWNERS deleted file mode 100644 index e9845a74729..00000000000 --- a/pkg/kubelet/dockershim/network/OWNERS +++ /dev/null @@ -1,10 +0,0 @@ -# See the OWNERS docs at https://go.k8s.io/owners - -approvers: -- sig-network-driver-approvers -emeritus_approvers: -- matchstick -reviewers: -- sig-network-reviewers -labels: -- sig/network diff --git a/pkg/kubelet/dockershim/network/cni/cni.go b/pkg/kubelet/dockershim/network/cni/cni.go deleted file mode 100644 index fd9d1dbb19f..00000000000 --- a/pkg/kubelet/dockershim/network/cni/cni.go +++ /dev/null @@ -1,472 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cni - -import ( - "context" - "encoding/json" - "fmt" - "math" - "sort" - "strings" - "sync" - "time" - - "github.com/containernetworking/cni/libcni" - cnitypes "github.com/containernetworking/cni/pkg/types" - "k8s.io/apimachinery/pkg/util/wait" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/klog/v2" - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - "k8s.io/kubernetes/pkg/util/bandwidth" - utilslice "k8s.io/kubernetes/pkg/util/slice" - utilexec "k8s.io/utils/exec" -) - -const ( - // CNIPluginName is the name of CNI plugin - CNIPluginName = "cni" - - // defaultSyncConfigPeriod is the default period to sync CNI config - // TODO: consider making this value configurable or to be a more appropriate value. - defaultSyncConfigPeriod = time.Second * 5 - - // supported capabilities - // https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md - portMappingsCapability = "portMappings" - ipRangesCapability = "ipRanges" - bandwidthCapability = "bandwidth" - dnsCapability = "dns" -) - -type cniNetworkPlugin struct { - network.NoopNetworkPlugin - - loNetwork *cniNetwork - - sync.RWMutex - defaultNetwork *cniNetwork - - host network.Host - execer utilexec.Interface - nsenterPath string - confDir string - binDirs []string - cacheDir string - podCidr string -} - -type cniNetwork struct { - name string - NetworkConfig *libcni.NetworkConfigList - CNIConfig libcni.CNI - Capabilities []string -} - -// cniPortMapping maps to the standard CNI portmapping Capability -// see: https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md -type cniPortMapping struct { - HostPort int32 `json:"hostPort"` - ContainerPort int32 `json:"containerPort"` - Protocol string `json:"protocol"` - HostIP string `json:"hostIP"` -} - -// cniBandwidthEntry maps to the standard CNI bandwidth Capability -// see: https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md and -// https://github.com/containernetworking/plugins/blob/master/plugins/meta/bandwidth/README.md -type cniBandwidthEntry struct { - // IngressRate is the bandwidth rate in bits per second for traffic through container. 0 for no limit. If IngressRate is set, IngressBurst must also be set - IngressRate int `json:"ingressRate,omitempty"` - // IngressBurst is the bandwidth burst in bits for traffic through container. 0 for no limit. If IngressBurst is set, IngressRate must also be set - // NOTE: it's not used for now and defaults to 0. If IngressRate is set IngressBurst will be math.MaxInt32 ~ 2Gbit - IngressBurst int `json:"ingressBurst,omitempty"` - // EgressRate is the bandwidth is the bandwidth rate in bits per second for traffic through container. 0 for no limit. If EgressRate is set, EgressBurst must also be set - EgressRate int `json:"egressRate,omitempty"` - // EgressBurst is the bandwidth burst in bits for traffic through container. 0 for no limit. If EgressBurst is set, EgressRate must also be set - // NOTE: it's not used for now and defaults to 0. If EgressRate is set EgressBurst will be math.MaxInt32 ~ 2Gbit - EgressBurst int `json:"egressBurst,omitempty"` -} - -// cniIPRange maps to the standard CNI ip range Capability -type cniIPRange struct { - Subnet string `json:"subnet"` -} - -// cniDNSConfig maps to the windows CNI dns Capability. -// see: https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md -// Note that dns capability is only used for Windows containers. -type cniDNSConfig struct { - // List of DNS servers of the cluster. - Servers []string `json:"servers,omitempty"` - // List of DNS search domains of the cluster. - Searches []string `json:"searches,omitempty"` - // List of DNS options. - Options []string `json:"options,omitempty"` -} - -// SplitDirs : split dirs by "," -func SplitDirs(dirs string) []string { - // Use comma rather than colon to work better with Windows too - return strings.Split(dirs, ",") -} - -// ProbeNetworkPlugins : get the network plugin based on cni conf file and bin file -func ProbeNetworkPlugins(confDir, cacheDir string, binDirs []string) []network.NetworkPlugin { - old := binDirs - binDirs = make([]string, 0, len(binDirs)) - for _, dir := range old { - if dir != "" { - binDirs = append(binDirs, dir) - } - } - - plugin := &cniNetworkPlugin{ - defaultNetwork: nil, - loNetwork: getLoNetwork(binDirs), - execer: utilexec.New(), - confDir: confDir, - binDirs: binDirs, - cacheDir: cacheDir, - } - - // sync NetworkConfig in best effort during probing. - plugin.syncNetworkConfig() - return []network.NetworkPlugin{plugin} -} - -func getDefaultCNINetwork(confDir string, binDirs []string) (*cniNetwork, error) { - files, err := libcni.ConfFiles(confDir, []string{".conf", ".conflist", ".json"}) - switch { - case err != nil: - return nil, err - case len(files) == 0: - return nil, fmt.Errorf("no networks found in %s", confDir) - } - - cniConfig := &libcni.CNIConfig{Path: binDirs} - - sort.Strings(files) - for _, confFile := range files { - var confList *libcni.NetworkConfigList - if strings.HasSuffix(confFile, ".conflist") { - confList, err = libcni.ConfListFromFile(confFile) - if err != nil { - klog.InfoS("Error loading CNI config list file", "path", confFile, "err", err) - continue - } - } else { - conf, err := libcni.ConfFromFile(confFile) - if err != nil { - klog.InfoS("Error loading CNI config file", "path", confFile, "err", err) - continue - } - // Ensure the config has a "type" so we know what plugin to run. - // Also catches the case where somebody put a conflist into a conf file. - if conf.Network.Type == "" { - klog.InfoS("Error loading CNI config file: no 'type'; perhaps this is a .conflist?", "path", confFile) - continue - } - - confList, err = libcni.ConfListFromConf(conf) - if err != nil { - klog.InfoS("Error converting CNI config file to list", "path", confFile, "err", err) - continue - } - } - if len(confList.Plugins) == 0 { - klog.InfoS("CNI config list has no networks, skipping", "configList", string(confList.Bytes[:maxStringLengthInLog(len(confList.Bytes))])) - continue - } - - // Before using this CNI config, we have to validate it to make sure that - // all plugins of this config exist on disk - caps, err := cniConfig.ValidateNetworkList(context.TODO(), confList) - if err != nil { - klog.InfoS("Error validating CNI config list", "configList", string(confList.Bytes[:maxStringLengthInLog(len(confList.Bytes))]), "err", err) - continue - } - - klog.V(4).InfoS("Using CNI configuration file", "path", confFile) - - return &cniNetwork{ - name: confList.Name, - NetworkConfig: confList, - CNIConfig: cniConfig, - Capabilities: caps, - }, nil - } - return nil, fmt.Errorf("no valid networks found in %s", confDir) -} - -func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { - err := plugin.platformInit() - if err != nil { - return err - } - - plugin.host = host - - plugin.syncNetworkConfig() - - // start a goroutine to sync network config from confDir periodically to detect network config updates in every 5 seconds - go wait.Forever(plugin.syncNetworkConfig, defaultSyncConfigPeriod) - - return nil -} - -func (plugin *cniNetworkPlugin) syncNetworkConfig() { - network, err := getDefaultCNINetwork(plugin.confDir, plugin.binDirs) - if err != nil { - klog.InfoS("Unable to update cni config", "err", err) - return - } - plugin.setDefaultNetwork(network) -} - -func (plugin *cniNetworkPlugin) getDefaultNetwork() *cniNetwork { - plugin.RLock() - defer plugin.RUnlock() - return plugin.defaultNetwork -} - -func (plugin *cniNetworkPlugin) setDefaultNetwork(n *cniNetwork) { - plugin.Lock() - defer plugin.Unlock() - plugin.defaultNetwork = n -} - -func (plugin *cniNetworkPlugin) checkInitialized() error { - if plugin.getDefaultNetwork() == nil { - return fmt.Errorf("cni config uninitialized") - } - - if utilslice.ContainsString(plugin.getDefaultNetwork().Capabilities, ipRangesCapability, nil) && plugin.podCidr == "" { - return fmt.Errorf("cni config needs ipRanges but no PodCIDR set") - } - - return nil -} - -// Event handles any change events. The only event ever sent is the PodCIDR change. -// No network plugins support changing an already-set PodCIDR -func (plugin *cniNetworkPlugin) Event(name string, details map[string]interface{}) { - if name != network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE { - return - } - - plugin.Lock() - defer plugin.Unlock() - - podCIDR, ok := details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR].(string) - if !ok { - klog.InfoS("The event didn't contain pod CIDR", "event", network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE) - return - } - - if plugin.podCidr != "" { - klog.InfoS("Ignoring subsequent pod CIDR update to new cidr", "podCIDR", podCIDR) - return - } - - plugin.podCidr = podCIDR -} - -func (plugin *cniNetworkPlugin) Name() string { - return CNIPluginName -} - -func (plugin *cniNetworkPlugin) Status() error { - // Can't set up pods if we don't have any CNI network configs yet - return plugin.checkInitialized() -} - -func (plugin *cniNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations, options map[string]string) error { - if err := plugin.checkInitialized(); err != nil { - return err - } - netnsPath, err := plugin.host.GetNetNS(id.ID) - if err != nil { - return fmt.Errorf("CNI failed to retrieve network namespace path: %v", err) - } - - // Todo get the timeout from parent ctx - cniTimeoutCtx, cancelFunc := context.WithTimeout(context.Background(), network.CNITimeoutSec*time.Second) - defer cancelFunc() - // Windows doesn't have loNetwork. It comes only with Linux - if plugin.loNetwork != nil { - if _, err = plugin.addToNetwork(cniTimeoutCtx, plugin.loNetwork, name, namespace, id, netnsPath, annotations, options); err != nil { - return err - } - } - - _, err = plugin.addToNetwork(cniTimeoutCtx, plugin.getDefaultNetwork(), name, namespace, id, netnsPath, annotations, options) - return err -} - -func (plugin *cniNetworkPlugin) TearDownPod(namespace string, name string, id kubecontainer.ContainerID) error { - if err := plugin.checkInitialized(); err != nil { - return err - } - - // Lack of namespace should not be fatal on teardown - netnsPath, err := plugin.host.GetNetNS(id.ID) - if err != nil { - klog.InfoS("CNI failed to retrieve network namespace path", "err", err) - } - - // Todo get the timeout from parent ctx - cniTimeoutCtx, cancelFunc := context.WithTimeout(context.Background(), network.CNITimeoutSec*time.Second) - defer cancelFunc() - // Windows doesn't have loNetwork. It comes only with Linux - if plugin.loNetwork != nil { - // Loopback network deletion failure should not be fatal on teardown - if err := plugin.deleteFromNetwork(cniTimeoutCtx, plugin.loNetwork, name, namespace, id, netnsPath, nil); err != nil { - klog.InfoS("CNI failed to delete loopback network", "err", err) - } - } - - return plugin.deleteFromNetwork(cniTimeoutCtx, plugin.getDefaultNetwork(), name, namespace, id, netnsPath, nil) -} - -func (plugin *cniNetworkPlugin) addToNetwork(ctx context.Context, network *cniNetwork, podName string, podNamespace string, podSandboxID kubecontainer.ContainerID, podNetnsPath string, annotations, options map[string]string) (cnitypes.Result, error) { - rt, err := plugin.buildCNIRuntimeConf(podName, podNamespace, podSandboxID, podNetnsPath, annotations, options) - if err != nil { - klog.ErrorS(err, "Error adding network when building cni runtime conf") - return nil, err - } - - netConf, cniNet := network.NetworkConfig, network.CNIConfig - klog.V(4).InfoS("Adding pod to network", "pod", klog.KRef(podNamespace, podName), "podSandboxID", podSandboxID, "podNetnsPath", podNetnsPath, "networkType", netConf.Plugins[0].Network.Type, "networkName", netConf.Name) - res, err := cniNet.AddNetworkList(ctx, netConf, rt) - if err != nil { - klog.ErrorS(err, "Error adding pod to network", "pod", klog.KRef(podNamespace, podName), "podSandboxID", podSandboxID, "podNetnsPath", podNetnsPath, "networkType", netConf.Plugins[0].Network.Type, "networkName", netConf.Name) - return nil, err - } - klog.V(4).InfoS("Added pod to network", "pod", klog.KRef(podNamespace, podName), "podSandboxID", podSandboxID, "networkName", netConf.Name, "response", res) - return res, nil -} - -func (plugin *cniNetworkPlugin) deleteFromNetwork(ctx context.Context, network *cniNetwork, podName string, podNamespace string, podSandboxID kubecontainer.ContainerID, podNetnsPath string, annotations map[string]string) error { - rt, err := plugin.buildCNIRuntimeConf(podName, podNamespace, podSandboxID, podNetnsPath, annotations, nil) - if err != nil { - klog.ErrorS(err, "Error deleting network when building cni runtime conf") - return err - } - netConf, cniNet := network.NetworkConfig, network.CNIConfig - klog.V(4).InfoS("Deleting pod from network", "pod", klog.KRef(podNamespace, podName), "podSandboxID", podSandboxID, "podNetnsPath", podNetnsPath, "networkType", netConf.Plugins[0].Network.Type, "networkName", netConf.Name) - err = cniNet.DelNetworkList(ctx, netConf, rt) - // The pod may not get deleted successfully at the first time. - // Ignore "no such file or directory" error in case the network has already been deleted in previous attempts. - if err != nil && !strings.Contains(err.Error(), "no such file or directory") { - klog.ErrorS(err, "Error deleting pod from network", "pod", klog.KRef(podNamespace, podName), "podSandboxID", podSandboxID, "podNetnsPath", podNetnsPath, "networkType", netConf.Plugins[0].Network.Type, "networkName", netConf.Name) - return err - } - klog.V(4).InfoS("Deleted pod from network", "pod", klog.KRef(podNamespace, podName), "podSandboxID", podSandboxID, "networkType", netConf.Plugins[0].Network.Type, "networkName", netConf.Name) - return nil -} - -func (plugin *cniNetworkPlugin) buildCNIRuntimeConf(podName string, podNs string, podSandboxID kubecontainer.ContainerID, podNetnsPath string, annotations, options map[string]string) (*libcni.RuntimeConf, error) { - rt := &libcni.RuntimeConf{ - ContainerID: podSandboxID.ID, - NetNS: podNetnsPath, - IfName: network.DefaultInterfaceName, - CacheDir: plugin.cacheDir, - Args: [][2]string{ - {"IgnoreUnknown", "1"}, - {"K8S_POD_NAMESPACE", podNs}, - {"K8S_POD_NAME", podName}, - {"K8S_POD_INFRA_CONTAINER_ID", podSandboxID.ID}, - }, - } - - // port mappings are a cni capability-based args, rather than parameters - // to a specific plugin - portMappings, err := plugin.host.GetPodPortMappings(podSandboxID.ID) - if err != nil { - return nil, fmt.Errorf("could not retrieve port mappings: %v", err) - } - portMappingsParam := make([]cniPortMapping, 0, len(portMappings)) - for _, p := range portMappings { - if p.HostPort <= 0 { - continue - } - portMappingsParam = append(portMappingsParam, cniPortMapping{ - HostPort: p.HostPort, - ContainerPort: p.ContainerPort, - Protocol: strings.ToLower(string(p.Protocol)), - HostIP: p.HostIP, - }) - } - rt.CapabilityArgs = map[string]interface{}{ - portMappingsCapability: portMappingsParam, - } - - ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations) - if err != nil { - return nil, fmt.Errorf("failed to get pod bandwidth from annotations: %v", err) - } - if ingress != nil || egress != nil { - bandwidthParam := cniBandwidthEntry{} - if ingress != nil { - // see: https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md and - // https://github.com/containernetworking/plugins/blob/master/plugins/meta/bandwidth/README.md - // Rates are in bits per second, burst values are in bits. - bandwidthParam.IngressRate = int(ingress.Value()) - // Limit IngressBurst to math.MaxInt32, in practice limiting to 2Gbit is the equivalent of setting no limit - bandwidthParam.IngressBurst = math.MaxInt32 - } - if egress != nil { - bandwidthParam.EgressRate = int(egress.Value()) - // Limit EgressBurst to math.MaxInt32, in practice limiting to 2Gbit is the equivalent of setting no limit - bandwidthParam.EgressBurst = math.MaxInt32 - } - rt.CapabilityArgs[bandwidthCapability] = bandwidthParam - } - - // Set the PodCIDR - rt.CapabilityArgs[ipRangesCapability] = [][]cniIPRange{{{Subnet: plugin.podCidr}}} - - // Set dns capability args. - if dnsOptions, ok := options["dns"]; ok { - dnsConfig := runtimeapi.DNSConfig{} - err := json.Unmarshal([]byte(dnsOptions), &dnsConfig) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal dns config %q: %v", dnsOptions, err) - } - if dnsParam := buildDNSCapabilities(&dnsConfig); dnsParam != nil { - rt.CapabilityArgs[dnsCapability] = *dnsParam - } - } - - return rt, nil -} - -func maxStringLengthInLog(length int) int { - // we allow no more than 4096-length strings to be logged - const maxStringLength = 4096 - - if length < maxStringLength { - return length - } - return maxStringLength -} diff --git a/pkg/kubelet/dockershim/network/cni/cni_others.go b/pkg/kubelet/dockershim/network/cni/cni_others.go deleted file mode 100644 index 66446d30210..00000000000 --- a/pkg/kubelet/dockershim/network/cni/cni_others.go +++ /dev/null @@ -1,91 +0,0 @@ -//go:build !windows && !dockerless -// +build !windows,!dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cni - -import ( - "fmt" - - "github.com/containernetworking/cni/libcni" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" -) - -func getLoNetwork(binDirs []string) *cniNetwork { - loConfig, err := libcni.ConfListFromBytes([]byte(`{ - "cniVersion": "0.2.0", - "name": "cni-loopback", - "plugins":[{ - "type": "loopback" - }] -}`)) - if err != nil { - // The hardcoded config above should always be valid and unit tests will - // catch this - panic(err) - } - loNetwork := &cniNetwork{ - name: "lo", - NetworkConfig: loConfig, - CNIConfig: &libcni.CNIConfig{Path: binDirs}, - } - - return loNetwork -} - -func (plugin *cniNetworkPlugin) platformInit() error { - var err error - plugin.nsenterPath, err = plugin.execer.LookPath("nsenter") - if err != nil { - return err - } - return nil -} - -// TODO: Use the addToNetwork function to obtain the IP of the Pod. That will assume idempotent ADD call to the plugin. -// Also fix the runtime's call to Status function to be done only in the case that the IP is lost, no need to do periodic calls -func (plugin *cniNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*network.PodNetworkStatus, error) { - netnsPath, err := plugin.host.GetNetNS(id.ID) - if err != nil { - return nil, fmt.Errorf("CNI failed to retrieve network namespace path: %v", err) - } - if netnsPath == "" { - return nil, fmt.Errorf("cannot find the network namespace, skipping pod network status for container %q", id) - } - - ips, err := network.GetPodIPs(plugin.execer, plugin.nsenterPath, netnsPath, network.DefaultInterfaceName) - if err != nil { - return nil, err - } - - if len(ips) == 0 { - return nil, fmt.Errorf("cannot find pod IPs in the network namespace, skipping pod network status for container %q", id) - } - - return &network.PodNetworkStatus{ - IP: ips[0], - IPs: ips, - }, nil -} - -// buildDNSCapabilities builds cniDNSConfig from runtimeapi.DNSConfig. -func buildDNSCapabilities(dnsConfig *runtimeapi.DNSConfig) *cniDNSConfig { - return nil -} diff --git a/pkg/kubelet/dockershim/network/cni/cni_test.go b/pkg/kubelet/dockershim/network/cni/cni_test.go deleted file mode 100644 index 71704cc52ce..00000000000 --- a/pkg/kubelet/dockershim/network/cni/cni_test.go +++ /dev/null @@ -1,360 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cni - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "math/rand" - "net" - "os" - "path" - "reflect" - "testing" - "text/template" - - types020 "github.com/containernetworking/cni/pkg/types/020" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "k8s.io/api/core/v1" - clientset "k8s.io/client-go/kubernetes" - utiltesting "k8s.io/client-go/util/testing" - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" - networktest "k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing" - "k8s.io/utils/exec" - fakeexec "k8s.io/utils/exec/testing" -) - -// Returns .in file path, .out file path, and .env file path -func installPluginUnderTest(t *testing.T, testBinDir, testConfDir, testDataDir, binName string, confName, podIP string) (string, string, string) { - for _, dir := range []string{testBinDir, testConfDir, testDataDir} { - err := os.MkdirAll(dir, 0777) - if err != nil { - t.Fatalf("Failed to create test plugin dir %s: %v", dir, err) - } - } - - const cniVersion = "0.2.0" - - confFile := path.Join(testConfDir, confName+".conf") - f, err := os.Create(confFile) - if err != nil { - t.Fatalf("Failed to install plugin %s: %v", confFile, err) - } - networkConfig := fmt.Sprintf(`{ "cniVersion": "%s", "name": "%s", "type": "%s", "capabilities": {"portMappings": true, "bandwidth": true, "ipRanges": true} }`, cniVersion, confName, binName) - _, err = f.WriteString(networkConfig) - if err != nil { - t.Fatalf("Failed to write network config file (%v)", err) - } - f.Close() - - pluginExec := path.Join(testBinDir, binName) - f, err = os.Create(pluginExec) - require.NoError(t, err) - - // TODO: use mock instead of fake shell script plugin - const execScriptTempl = `#!/usr/bin/env bash -echo -n "{ \"cniVersion\": \"{{.CNIVersion}}\", \"ip4\": { \"ip\": \"{{.PodIP}}/24\" } }" -if [ "$CNI_COMMAND" = "VERSION" ]; then - exit -fi -cat > {{.InputFile}} -env > {{.OutputEnv}} -echo "%@" >> {{.OutputEnv}} -export $(echo ${CNI_ARGS} | sed 's/;/ /g') &> /dev/null -mkdir -p {{.OutputDir}} &> /dev/null -echo -n "$CNI_COMMAND $CNI_NETNS $K8S_POD_NAMESPACE $K8S_POD_NAME $K8S_POD_INFRA_CONTAINER_ID" >& {{.OutputFile}}` - - inputFile := path.Join(testDataDir, binName+".in") - outputFile := path.Join(testDataDir, binName+".out") - envFile := path.Join(testDataDir, binName+".env") - execTemplateData := &map[string]interface{}{ - "InputFile": inputFile, - "OutputFile": outputFile, - "OutputEnv": envFile, - "OutputDir": testDataDir, - "CNIVersion": cniVersion, - "PodIP": podIP, - } - - tObj := template.Must(template.New("test").Parse(execScriptTempl)) - buf := &bytes.Buffer{} - if err := tObj.Execute(buf, *execTemplateData); err != nil { - t.Fatalf("Error in executing script template - %v", err) - } - execScript := buf.String() - _, err = f.WriteString(execScript) - if err != nil { - t.Fatalf("Failed to write plugin exec - %v", err) - } - - err = f.Chmod(0777) - if err != nil { - t.Fatalf("Failed to set exec perms on plugin") - } - - f.Close() - - return inputFile, outputFile, envFile -} - -func tearDownPlugin(tmpDir string) { - err := os.RemoveAll(tmpDir) - if err != nil { - fmt.Printf("Error in cleaning up test: %v", err) - } -} - -type FakeNetworkHost struct { - networktest.FakePortMappingGetter - kubeClient clientset.Interface - pods []*containertest.FakePod -} - -func NewFakeHost(kubeClient clientset.Interface, pods []*containertest.FakePod, ports map[string][]*hostport.PortMapping) *FakeNetworkHost { - host := &FakeNetworkHost{ - networktest.FakePortMappingGetter{PortMaps: ports}, - kubeClient, - pods, - } - return host -} - -func (fnh *FakeNetworkHost) GetPodByName(name, namespace string) (*v1.Pod, bool) { - return nil, false -} - -func (fnh *FakeNetworkHost) GetKubeClient() clientset.Interface { - return fnh.kubeClient -} - -func (fnh *FakeNetworkHost) GetNetNS(containerID string) (string, error) { - for _, fp := range fnh.pods { - for _, c := range fp.Pod.Containers { - if c.ID.ID == containerID { - return fp.NetnsPath, nil - } - } - } - return "", fmt.Errorf("container %q not found", containerID) -} - -func (fnh *FakeNetworkHost) SupportsLegacyFeatures() bool { - return true -} - -func TestCNIPlugin(t *testing.T) { - // install some random plugin - netName := fmt.Sprintf("test%d", rand.Intn(1000)) - binName := fmt.Sprintf("test_vendor%d", rand.Intn(1000)) - - podIP := "10.0.0.2" - podIPOutput := fmt.Sprintf("4: eth0 inet %s/24 scope global dynamic eth0\\ valid_lft forever preferred_lft forever", podIP) - fakeCmds := []fakeexec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { - return fakeexec.InitFakeCmd(&fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeAction{ - func() ([]byte, []byte, error) { - return []byte(podIPOutput), nil, nil - }, - }, - }, cmd, args...) - }, - func(cmd string, args ...string) exec.Cmd { - return fakeexec.InitFakeCmd(&fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeAction{ - func() ([]byte, []byte, error) { - return []byte(podIPOutput), nil, nil - }, - }, - }, cmd, args...) - }, - } - - fexec := &fakeexec.FakeExec{ - CommandScript: fakeCmds, - LookPathFunc: func(file string) (string, error) { - return fmt.Sprintf("/fake-bin/%s", file), nil - }, - } - - mockLoCNI := &mock_cni.MockCNI{} - // TODO mock for the test plugin too - - tmpDir := utiltesting.MkTmpdirOrDie("cni-test") - testConfDir := path.Join(tmpDir, "etc", "cni", "net.d") - testBinDir := path.Join(tmpDir, "opt", "cni", "bin") - testDataDir := path.Join(tmpDir, "output") - testCacheDir := path.Join(tmpDir, "var", "lib", "cni", "cache") - defer tearDownPlugin(tmpDir) - inputFile, outputFile, outputEnv := installPluginUnderTest(t, testBinDir, testConfDir, testDataDir, binName, netName, podIP) - - containerID := kubecontainer.ContainerID{Type: "test", ID: "test_infra_container"} - pods := []*containertest.FakePod{{ - Pod: &kubecontainer.Pod{ - Containers: []*kubecontainer.Container{ - {ID: containerID}, - }, - }, - NetnsPath: "/proc/12345/ns/net", - }} - - plugins := ProbeNetworkPlugins(testConfDir, testCacheDir, []string{testBinDir}) - if len(plugins) != 1 { - t.Fatalf("Expected only one network plugin, got %d", len(plugins)) - } - if plugins[0].Name() != "cni" { - t.Fatalf("Expected CNI network plugin, got %q", plugins[0].Name()) - } - - cniPlugin, ok := plugins[0].(*cniNetworkPlugin) - if !ok { - t.Fatalf("Not a CNI network plugin!") - } - cniPlugin.execer = fexec - cniPlugin.loNetwork.CNIConfig = mockLoCNI - - mockLoCNI.On("AddNetworkList", mock.AnythingOfType("*context.timerCtx"), cniPlugin.loNetwork.NetworkConfig, mock.AnythingOfType("*libcni.RuntimeConf")).Return(&types020.Result{IP4: &types020.IPConfig{IP: net.IPNet{IP: []byte{127, 0, 0, 1}}}}, nil) - mockLoCNI.On("DelNetworkList", mock.AnythingOfType("*context.timerCtx"), cniPlugin.loNetwork.NetworkConfig, mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil) - - // Check that status returns an error - if err := cniPlugin.Status(); err == nil { - t.Fatalf("cniPlugin returned non-err with no podCidr") - } - - cniPlugin.Event(network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE, map[string]interface{}{ - network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR: "10.0.2.0/24", - }) - - if err := cniPlugin.Status(); err != nil { - t.Fatalf("unexpected status err: %v", err) - } - - ports := map[string][]*hostport.PortMapping{ - containerID.ID: { - { - HostPort: 8008, - ContainerPort: 80, - Protocol: "UDP", - HostIP: "0.0.0.0", - }, - }, - } - fakeHost := NewFakeHost(nil, pods, ports) - - plug, err := network.InitNetworkPlugin(plugins, "cni", fakeHost, kubeletconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU) - if err != nil { - t.Fatalf("Failed to select the desired plugin: %v", err) - } - - bandwidthAnnotation := make(map[string]string) - bandwidthAnnotation["kubernetes.io/ingress-bandwidth"] = "1M" - bandwidthAnnotation["kubernetes.io/egress-bandwidth"] = "1M" - - // Set up the pod - err = plug.SetUpPod("podNamespace", "podName", containerID, bandwidthAnnotation, nil) - if err != nil { - t.Errorf("Expected nil: %v", err) - } - eo, eerr := ioutil.ReadFile(outputEnv) - output, err := ioutil.ReadFile(outputFile) - if err != nil || eerr != nil { - t.Errorf("Failed to read output file %s: %v (env %s err %v)", outputFile, err, eo, eerr) - } - - expectedOutput := "ADD /proc/12345/ns/net podNamespace podName test_infra_container" - if string(output) != expectedOutput { - t.Errorf("Mismatch in expected output for setup hook. Expected '%s', got '%s'", expectedOutput, string(output)) - } - - // Verify the correct network configuration was passed - inputConfig := struct { - RuntimeConfig struct { - PortMappings []map[string]interface{} `json:"portMappings"` - Bandwidth map[string]interface{} `json:"bandwidth"` - IPRanges [][]map[string]interface{} `json:"IPRanges"` - } `json:"runtimeConfig"` - }{} - inputBytes, inerr := ioutil.ReadFile(inputFile) - parseerr := json.Unmarshal(inputBytes, &inputConfig) - if inerr != nil || parseerr != nil { - t.Errorf("failed to parse reported cni input config %s: (%v %v)", inputFile, inerr, parseerr) - } - expectedMappings := []map[string]interface{}{ - // hah, golang always unmarshals unstructured json numbers as float64 - {"hostPort": 8008.0, "containerPort": 80.0, "protocol": "udp", "hostIP": "0.0.0.0"}, - } - if !reflect.DeepEqual(inputConfig.RuntimeConfig.PortMappings, expectedMappings) { - t.Errorf("mismatch in expected port mappings. expected %v got %v", expectedMappings, inputConfig.RuntimeConfig.PortMappings) - } - expectedBandwidth := map[string]interface{}{ - "ingressRate": 1000000.0, "egressRate": 1000000.0, - "ingressBurst": 2147483647.0, "egressBurst": 2147483647.0, - } - if !reflect.DeepEqual(inputConfig.RuntimeConfig.Bandwidth, expectedBandwidth) { - t.Errorf("mismatch in expected bandwidth. expected %v got %v", expectedBandwidth, inputConfig.RuntimeConfig.Bandwidth) - } - - expectedIPRange := [][]map[string]interface{}{ - { - {"subnet": "10.0.2.0/24"}, - }, - } - - if !reflect.DeepEqual(inputConfig.RuntimeConfig.IPRanges, expectedIPRange) { - t.Errorf("mismatch in expected ipRange. expected %v got %v", expectedIPRange, inputConfig.RuntimeConfig.IPRanges) - } - - // Get its IP address - status, err := plug.GetPodNetworkStatus("podNamespace", "podName", containerID) - if err != nil { - t.Errorf("Failed to read pod network status: %v", err) - } - if status.IP.String() != podIP { - t.Errorf("Expected pod IP %q but got %q", podIP, status.IP.String()) - } - - // Tear it down - err = plug.TearDownPod("podNamespace", "podName", containerID) - if err != nil { - t.Errorf("Expected nil: %v", err) - } - output, err = ioutil.ReadFile(outputFile) - require.NoError(t, err) - expectedOutput = "DEL /proc/12345/ns/net podNamespace podName test_infra_container" - if string(output) != expectedOutput { - t.Errorf("Mismatch in expected output for setup hook. Expected '%s', got '%s'", expectedOutput, string(output)) - } - - mockLoCNI.AssertExpectations(t) -} - -func TestLoNetNonNil(t *testing.T) { - if conf := getLoNetwork(nil); conf == nil { - t.Error("Expected non-nil lo network") - } -} diff --git a/pkg/kubelet/dockershim/network/cni/cni_windows.go b/pkg/kubelet/dockershim/network/cni/cni_windows.go deleted file mode 100644 index f1b4aca6fe5..00000000000 --- a/pkg/kubelet/dockershim/network/cni/cni_windows.go +++ /dev/null @@ -1,92 +0,0 @@ -//go:build windows && !dockerless -// +build windows,!dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cni - -import ( - "context" - "fmt" - cniTypes020 "github.com/containernetworking/cni/pkg/types/020" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/klog/v2" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - "net" - "time" -) - -func getLoNetwork(binDirs []string) *cniNetwork { - return nil -} - -func (plugin *cniNetworkPlugin) platformInit() error { - return nil -} - -// GetPodNetworkStatus : Assuming addToNetwork is idempotent, we can call this API as many times as required to get the IPAddress -func (plugin *cniNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*network.PodNetworkStatus, error) { - netnsPath, err := plugin.host.GetNetNS(id.ID) - if err != nil { - return nil, fmt.Errorf("CNI failed to retrieve network namespace path: %v", err) - } - - if plugin.getDefaultNetwork() == nil { - return nil, fmt.Errorf("CNI network not yet initialized, skipping pod network status for container %q", id) - } - - // Because the default remote runtime request timeout is 4 min,so set slightly less than 240 seconds - // Todo get the timeout from parent ctx - cniTimeoutCtx, cancelFunc := context.WithTimeout(context.Background(), network.CNITimeoutSec*time.Second) - defer cancelFunc() - result, err := plugin.addToNetwork(cniTimeoutCtx, plugin.getDefaultNetwork(), name, namespace, id, netnsPath, nil, nil) - klog.V(5).InfoS("GetPodNetworkStatus", "result", result) - if err != nil { - klog.ErrorS(err, "Got error while adding to cni network") - return nil, err - } - - // Parse the result and get the IPAddress - var result020 *cniTypes020.Result - result020, err = cniTypes020.GetResult(result) - if err != nil { - klog.ErrorS(err, "Got error while cni parsing result") - return nil, err - } - - var list = []net.IP{result020.IP4.IP.IP} - - if result020.IP6 != nil { - list = append(list, result020.IP6.IP.IP) - } - - return &network.PodNetworkStatus{IP: result020.IP4.IP.IP, IPs: list}, nil -} - -// buildDNSCapabilities builds cniDNSConfig from runtimeapi.DNSConfig. -func buildDNSCapabilities(dnsConfig *runtimeapi.DNSConfig) *cniDNSConfig { - if dnsConfig != nil { - return &cniDNSConfig{ - Servers: dnsConfig.Servers, - Searches: dnsConfig.Searches, - Options: dnsConfig.Options, - } - } - - return nil -} diff --git a/pkg/kubelet/dockershim/network/cni/testing/mock_cni.go b/pkg/kubelet/dockershim/network/cni/testing/mock_cni.go deleted file mode 100644 index 550137ef0e9..00000000000 --- a/pkg/kubelet/dockershim/network/cni/testing/mock_cni.go +++ /dev/null @@ -1,94 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes 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. -*/ - -// mock_cni is a mock of the `libcni.CNI` interface. It's a handwritten mock -// because there are only two functions to deal with. -package mock_cni - -import ( - "context" - - "github.com/containernetworking/cni/libcni" - "github.com/containernetworking/cni/pkg/types" - "github.com/stretchr/testify/mock" -) - -type MockCNI struct { - mock.Mock -} - -func (m *MockCNI) AddNetwork(ctx context.Context, net *libcni.NetworkConfig, rt *libcni.RuntimeConf) (types.Result, error) { - args := m.Called(ctx, net, rt) - return args.Get(0).(types.Result), args.Error(1) -} - -func (m *MockCNI) DelNetwork(ctx context.Context, net *libcni.NetworkConfig, rt *libcni.RuntimeConf) error { - args := m.Called(ctx, net, rt) - return args.Error(0) -} - -func (m *MockCNI) DelNetworkList(ctx context.Context, net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) error { - args := m.Called(ctx, net, rt) - return args.Error(0) -} - -func (m *MockCNI) GetNetworkListCachedConfig(net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) ([]byte, *libcni.RuntimeConf, error) { - args := m.Called(net, rt) - return args.Get(0).([]byte), args.Get(1).(*libcni.RuntimeConf), args.Error(1) -} - -func (m *MockCNI) GetNetworkListCachedResult(net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) (types.Result, error) { - args := m.Called(net, rt) - return args.Get(0).(types.Result), args.Error(1) -} - -func (m *MockCNI) AddNetworkList(ctx context.Context, net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) (types.Result, error) { - args := m.Called(ctx, net, rt) - return args.Get(0).(types.Result), args.Error(1) -} - -func (m *MockCNI) CheckNetworkList(ctx context.Context, net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) error { - args := m.Called(ctx, net, rt) - return args.Error(0) -} - -func (m *MockCNI) CheckNetwork(ctx context.Context, net *libcni.NetworkConfig, rt *libcni.RuntimeConf) error { - args := m.Called(ctx, net, rt) - return args.Error(0) -} - -func (m *MockCNI) GetNetworkCachedConfig(net *libcni.NetworkConfig, rt *libcni.RuntimeConf) ([]byte, *libcni.RuntimeConf, error) { - args := m.Called(net, rt) - return args.Get(0).([]byte), args.Get(1).(*libcni.RuntimeConf), args.Error(1) -} - -func (m *MockCNI) GetNetworkCachedResult(net *libcni.NetworkConfig, rt *libcni.RuntimeConf) (types.Result, error) { - args := m.Called(net, rt) - return args.Get(0).(types.Result), args.Error(0) -} - -func (m *MockCNI) ValidateNetworkList(ctx context.Context, net *libcni.NetworkConfigList) ([]string, error) { - args := m.Called(ctx, net) - return args.Get(0).([]string), args.Error(0) -} - -func (m *MockCNI) ValidateNetwork(ctx context.Context, net *libcni.NetworkConfig) ([]string, error) { - args := m.Called(ctx, net) - return args.Get(0).([]string), args.Error(0) -} diff --git a/pkg/kubelet/dockershim/network/hairpin/hairpin.go b/pkg/kubelet/dockershim/network/hairpin/hairpin.go deleted file mode 100644 index ca6fc3bb7fa..00000000000 --- a/pkg/kubelet/dockershim/network/hairpin/hairpin.go +++ /dev/null @@ -1,90 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hairpin - -import ( - "fmt" - "io/ioutil" - "net" - "os" - "path" - "regexp" - "strconv" - - "k8s.io/klog/v2" - "k8s.io/utils/exec" -) - -const ( - sysfsNetPath = "/sys/devices/virtual/net" - brportRelativePath = "brport" - hairpinModeRelativePath = "hairpin_mode" - hairpinEnable = "1" -) - -var ( - ethtoolOutputRegex = regexp.MustCompile(`peer_ifindex: (\d+)`) -) - -func findPairInterfaceOfContainerInterface(e exec.Interface, containerInterfaceName, containerDesc string, nsenterArgs []string) (string, error) { - nsenterPath, err := e.LookPath("nsenter") - if err != nil { - return "", err - } - ethtoolPath, err := e.LookPath("ethtool") - if err != nil { - return "", err - } - - nsenterArgs = append(nsenterArgs, "-F", "--", ethtoolPath, "--statistics", containerInterfaceName) - output, err := e.Command(nsenterPath, nsenterArgs...).CombinedOutput() - if err != nil { - return "", fmt.Errorf("unable to query interface %s of container %s: %v: %s", containerInterfaceName, containerDesc, err, string(output)) - } - // look for peer_ifindex - match := ethtoolOutputRegex.FindSubmatch(output) - if match == nil { - return "", fmt.Errorf("no peer_ifindex in interface statistics for %s of container %s", containerInterfaceName, containerDesc) - } - peerIfIndex, err := strconv.Atoi(string(match[1])) - if err != nil { // seems impossible (\d+ not numeric) - return "", fmt.Errorf("peer_ifindex wasn't numeric: %s: %v", match[1], err) - } - iface, err := net.InterfaceByIndex(peerIfIndex) - if err != nil { - return "", err - } - return iface.Name, nil -} - -func setUpInterface(ifName string) error { - klog.V(3).InfoS("Enabling hairpin on interface", "interfaceName", ifName) - ifPath := path.Join(sysfsNetPath, ifName) - if _, err := os.Stat(ifPath); err != nil { - return err - } - brportPath := path.Join(ifPath, brportRelativePath) - if _, err := os.Stat(brportPath); err != nil && os.IsNotExist(err) { - // Device is not on a bridge, so doesn't need hairpin mode - return nil - } - hairpinModeFile := path.Join(brportPath, hairpinModeRelativePath) - return ioutil.WriteFile(hairpinModeFile, []byte(hairpinEnable), 0644) -} diff --git a/pkg/kubelet/dockershim/network/hairpin/hairpin_test.go b/pkg/kubelet/dockershim/network/hairpin/hairpin_test.go deleted file mode 100644 index 9930d569287..00000000000 --- a/pkg/kubelet/dockershim/network/hairpin/hairpin_test.go +++ /dev/null @@ -1,112 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hairpin - -import ( - "errors" - "fmt" - "net" - "os" - "strings" - "testing" - - "k8s.io/utils/exec" - fakeexec "k8s.io/utils/exec/testing" -) - -func TestFindPairInterfaceOfContainerInterface(t *testing.T) { - // there should be at least "lo" on any system - interfaces, _ := net.Interfaces() - validOutput := fmt.Sprintf("garbage\n peer_ifindex: %d", interfaces[0].Index) - invalidOutput := fmt.Sprintf("garbage\n unknown: %d", interfaces[0].Index) - - tests := []struct { - output string - err error - expectedName string - expectErr bool - }{ - { - output: validOutput, - expectedName: interfaces[0].Name, - }, - { - output: invalidOutput, - expectErr: true, - }, - { - output: validOutput, - err: errors.New("error"), - expectErr: true, - }, - } - for _, test := range tests { - fcmd := fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeAction{ - func() ([]byte, []byte, error) { return []byte(test.output), nil, test.err }, - }, - } - fexec := fakeexec.FakeExec{ - CommandScript: []fakeexec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { - return fakeexec.InitFakeCmd(&fcmd, cmd, args...) - }, - }, - LookPathFunc: func(file string) (string, error) { - return fmt.Sprintf("/fake-bin/%s", file), nil - }, - } - nsenterArgs := []string{"-t", "123", "-n"} - name, err := findPairInterfaceOfContainerInterface(&fexec, "eth0", "123", nsenterArgs) - if test.expectErr { - if err == nil { - t.Errorf("unexpected non-error") - } - } else { - if err != nil { - t.Errorf("unexpected error: %v", err) - } - } - if name != test.expectedName { - t.Errorf("unexpected name: %s (expected: %s)", name, test.expectedName) - } - } -} - -func TestSetUpInterfaceNonExistent(t *testing.T) { - err := setUpInterface("non-existent") - if err == nil { - t.Errorf("unexpected non-error") - } - deviceDir := fmt.Sprintf("%s/%s", sysfsNetPath, "non-existent") - if !strings.Contains(fmt.Sprintf("%v", err), deviceDir) { - t.Errorf("should have tried to open %s", deviceDir) - } -} - -func TestSetUpInterfaceNotBridged(t *testing.T) { - err := setUpInterface("lo") - if err != nil { - if os.IsNotExist(err) { - t.Skipf("'lo' device does not exist??? (%v)", err) - } - t.Errorf("unexpected error: %v", err) - } -} diff --git a/pkg/kubelet/dockershim/network/hostport/fake_iptables.go b/pkg/kubelet/dockershim/network/hostport/fake_iptables.go deleted file mode 100644 index 6d7a51fce93..00000000000 --- a/pkg/kubelet/dockershim/network/hostport/fake_iptables.go +++ /dev/null @@ -1,375 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hostport - -import ( - "bytes" - "fmt" - "strings" - "time" - - "k8s.io/apimachinery/pkg/util/sets" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" - netutils "k8s.io/utils/net" -) - -type fakeChain struct { - name utiliptables.Chain - rules []string -} - -type fakeTable struct { - name utiliptables.Table - chains map[string]*fakeChain -} - -type fakeIPTables struct { - tables map[string]*fakeTable - builtinChains map[string]sets.String - protocol utiliptables.Protocol -} - -func NewFakeIPTables() *fakeIPTables { - return &fakeIPTables{ - tables: make(map[string]*fakeTable), - builtinChains: map[string]sets.String{ - string(utiliptables.TableFilter): sets.NewString("INPUT", "FORWARD", "OUTPUT"), - string(utiliptables.TableNAT): sets.NewString("PREROUTING", "INPUT", "OUTPUT", "POSTROUTING"), - string(utiliptables.TableMangle): sets.NewString("PREROUTING", "INPUT", "FORWARD", "OUTPUT", "POSTROUTING"), - }, - protocol: utiliptables.ProtocolIPv4, - } -} - -func (f *fakeIPTables) getTable(tableName utiliptables.Table) (*fakeTable, error) { - table, ok := f.tables[string(tableName)] - if !ok { - return nil, fmt.Errorf("table %s does not exist", tableName) - } - return table, nil -} - -func (f *fakeIPTables) getChain(tableName utiliptables.Table, chainName utiliptables.Chain) (*fakeTable, *fakeChain, error) { - table, err := f.getTable(tableName) - if err != nil { - return nil, nil, err - } - - chain, ok := table.chains[string(chainName)] - if !ok { - return table, nil, fmt.Errorf("chain %s/%s does not exist", tableName, chainName) - } - - return table, chain, nil -} - -func (f *fakeIPTables) ensureChain(tableName utiliptables.Table, chainName utiliptables.Chain) (bool, *fakeChain) { - table, chain, err := f.getChain(tableName, chainName) - if err != nil { - // either table or table+chain don't exist yet - if table == nil { - table = &fakeTable{ - name: tableName, - chains: make(map[string]*fakeChain), - } - f.tables[string(tableName)] = table - } - chain := &fakeChain{ - name: chainName, - rules: make([]string, 0), - } - table.chains[string(chainName)] = chain - return false, chain - } - return true, chain -} - -func (f *fakeIPTables) EnsureChain(tableName utiliptables.Table, chainName utiliptables.Chain) (bool, error) { - existed, _ := f.ensureChain(tableName, chainName) - return existed, nil -} - -func (f *fakeIPTables) FlushChain(tableName utiliptables.Table, chainName utiliptables.Chain) error { - _, chain, err := f.getChain(tableName, chainName) - if err != nil { - return err - } - chain.rules = make([]string, 0) - return nil -} - -func (f *fakeIPTables) DeleteChain(tableName utiliptables.Table, chainName utiliptables.Chain) error { - table, _, err := f.getChain(tableName, chainName) - if err != nil { - return err - } - delete(table.chains, string(chainName)) - return nil -} - -func (f *fakeIPTables) ChainExists(tableName utiliptables.Table, chainName utiliptables.Chain) (bool, error) { - _, _, err := f.getChain(tableName, chainName) - if err != nil { - return false, err - } - return true, nil -} - -// Returns index of rule in array; < 0 if rule is not found -func findRule(chain *fakeChain, rule string) int { - for i, candidate := range chain.rules { - if rule == candidate { - return i - } - } - return -1 -} - -func (f *fakeIPTables) ensureRule(position utiliptables.RulePosition, tableName utiliptables.Table, chainName utiliptables.Chain, rule string) (bool, error) { - _, chain, err := f.getChain(tableName, chainName) - if err != nil { - _, chain = f.ensureChain(tableName, chainName) - } - - rule, err = normalizeRule(rule) - if err != nil { - return false, err - } - ruleIdx := findRule(chain, rule) - if ruleIdx >= 0 { - return true, nil - } - - switch position { - case utiliptables.Prepend: - chain.rules = append([]string{rule}, chain.rules...) - case utiliptables.Append: - chain.rules = append(chain.rules, rule) - default: - return false, fmt.Errorf("unknown position argument %q", position) - } - return false, nil -} - -func normalizeRule(rule string) (string, error) { - normalized := "" - remaining := strings.TrimSpace(rule) - for { - var end int - - if strings.HasPrefix(remaining, "--to-destination=") { - remaining = strings.Replace(remaining, "=", " ", 1) - } - - if remaining[0] == '"' { - end = strings.Index(remaining[1:], "\"") - if end < 0 { - return "", fmt.Errorf("invalid rule syntax: mismatched quotes") - } - end += 2 - } else { - end = strings.Index(remaining, " ") - if end < 0 { - end = len(remaining) - } - } - arg := remaining[:end] - - // Normalize un-prefixed IP addresses like iptables does - if netutils.ParseIPSloppy(arg) != nil { - arg += "/32" - } - - if len(normalized) > 0 { - normalized += " " - } - normalized += strings.TrimSpace(arg) - if len(remaining) == end { - break - } - remaining = remaining[end+1:] - } - return normalized, nil -} - -func (f *fakeIPTables) EnsureRule(position utiliptables.RulePosition, tableName utiliptables.Table, chainName utiliptables.Chain, args ...string) (bool, error) { - ruleArgs := make([]string, 0) - for _, arg := range args { - // quote args with internal spaces (like comments) - if strings.Contains(arg, " ") { - arg = fmt.Sprintf("\"%s\"", arg) - } - ruleArgs = append(ruleArgs, arg) - } - return f.ensureRule(position, tableName, chainName, strings.Join(ruleArgs, " ")) -} - -func (f *fakeIPTables) DeleteRule(tableName utiliptables.Table, chainName utiliptables.Chain, args ...string) error { - _, chain, err := f.getChain(tableName, chainName) - if err == nil { - rule := strings.Join(args, " ") - ruleIdx := findRule(chain, rule) - if ruleIdx < 0 { - return nil - } - chain.rules = append(chain.rules[:ruleIdx], chain.rules[ruleIdx+1:]...) - } - return nil -} - -func (f *fakeIPTables) IsIPv6() bool { - return f.protocol == utiliptables.ProtocolIPv6 -} - -func (f *fakeIPTables) Protocol() utiliptables.Protocol { - return f.protocol -} - -func saveChain(chain *fakeChain, data *bytes.Buffer) { - for _, rule := range chain.rules { - data.WriteString(fmt.Sprintf("-A %s %s\n", chain.name, rule)) - } -} - -func (f *fakeIPTables) SaveInto(tableName utiliptables.Table, buffer *bytes.Buffer) error { - table, err := f.getTable(tableName) - if err != nil { - return err - } - - buffer.WriteString(fmt.Sprintf("*%s\n", table.name)) - - rules := bytes.NewBuffer(nil) - for _, chain := range table.chains { - buffer.WriteString(fmt.Sprintf(":%s - [0:0]\n", string(chain.name))) - saveChain(chain, rules) - } - buffer.Write(rules.Bytes()) - buffer.WriteString("COMMIT\n") - return nil -} - -func (f *fakeIPTables) restore(restoreTableName utiliptables.Table, data []byte, flush utiliptables.FlushFlag) error { - allLines := string(data) - buf := bytes.NewBuffer(data) - var tableName utiliptables.Table - for { - line, err := buf.ReadString('\n') - if err != nil { - break - } - if line[0] == '#' { - continue - } - - line = strings.TrimSuffix(line, "\n") - if strings.HasPrefix(line, "*") { - tableName = utiliptables.Table(line[1:]) - } - if tableName != "" { - if restoreTableName != "" && restoreTableName != tableName { - continue - } - if strings.HasPrefix(line, ":") { - chainName := utiliptables.Chain(strings.Split(line[1:], " ")[0]) - if flush == utiliptables.FlushTables { - table, chain, err := f.getChain(tableName, chainName) - if err != nil { - return err - } - if chain != nil { - delete(table.chains, string(chainName)) - } - } - _, _ = f.ensureChain(tableName, chainName) - // The --noflush option for iptables-restore doesn't work for user-defined chains, only builtin chains. - // We should flush user-defined chains if the chain is not to be deleted - if !f.isBuiltinChain(tableName, chainName) && !strings.Contains(allLines, "-X "+string(chainName)) { - if err := f.FlushChain(tableName, chainName); err != nil { - return err - } - } - } else if strings.HasPrefix(line, "-A") { - parts := strings.Split(line, " ") - if len(parts) < 3 { - return fmt.Errorf("invalid iptables rule '%s'", line) - } - chainName := utiliptables.Chain(parts[1]) - rule := strings.TrimPrefix(line, fmt.Sprintf("-A %s ", chainName)) - _, err := f.ensureRule(utiliptables.Append, tableName, chainName, rule) - if err != nil { - return err - } - } else if strings.HasPrefix(line, "-I") { - parts := strings.Split(line, " ") - if len(parts) < 3 { - return fmt.Errorf("invalid iptables rule '%s'", line) - } - chainName := utiliptables.Chain(parts[1]) - rule := strings.TrimPrefix(line, fmt.Sprintf("-I %s ", chainName)) - _, err := f.ensureRule(utiliptables.Prepend, tableName, chainName, rule) - if err != nil { - return err - } - } else if strings.HasPrefix(line, "-X") { - parts := strings.Split(line, " ") - if len(parts) < 2 { - return fmt.Errorf("invalid iptables rule '%s'", line) - } - if err := f.DeleteChain(tableName, utiliptables.Chain(parts[1])); err != nil { - return err - } - } else if line == "COMMIT" { - if restoreTableName == tableName { - return nil - } - tableName = "" - } - } - } - - return nil -} - -func (f *fakeIPTables) Restore(tableName utiliptables.Table, data []byte, flush utiliptables.FlushFlag, counters utiliptables.RestoreCountersFlag) error { - return f.restore(tableName, data, flush) -} - -func (f *fakeIPTables) RestoreAll(data []byte, flush utiliptables.FlushFlag, counters utiliptables.RestoreCountersFlag) error { - return f.restore("", data, flush) -} - -func (f *fakeIPTables) Monitor(canary utiliptables.Chain, tables []utiliptables.Table, reloadFunc func(), interval time.Duration, stopCh <-chan struct{}) { -} - -func (f *fakeIPTables) isBuiltinChain(tableName utiliptables.Table, chainName utiliptables.Chain) bool { - if builtinChains, ok := f.builtinChains[string(tableName)]; ok && builtinChains.Has(string(chainName)) { - return true - } - return false -} - -func (f *fakeIPTables) HasRandomFully() bool { - return false -} - -func (f *fakeIPTables) Present() bool { - return true -} diff --git a/pkg/kubelet/dockershim/network/hostport/fake_iptables_test.go b/pkg/kubelet/dockershim/network/hostport/fake_iptables_test.go deleted file mode 100644 index 41dd7ba7390..00000000000 --- a/pkg/kubelet/dockershim/network/hostport/fake_iptables_test.go +++ /dev/null @@ -1,59 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hostport - -import ( - "bytes" - "testing" - - "github.com/stretchr/testify/assert" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" -) - -func TestRestoreFlushRules(t *testing.T) { - iptables := NewFakeIPTables() - rules := [][]string{ - {"-A", "KUBE-HOSTPORTS", "-m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp --dport 8443 -j KUBE-HP-5N7UH5JAXCVP5UJR"}, - {"-A", "POSTROUTING", "-m comment --comment \"SNAT for localhost access to hostports\" -o cbr0 -s 127.0.0.0/8 -j MASQUERADE"}, - } - natRules := bytes.NewBuffer(nil) - writeLine(natRules, "*nat") - for _, rule := range rules { - _, err := iptables.EnsureChain(utiliptables.TableNAT, utiliptables.Chain(rule[1])) - assert.NoError(t, err) - _, err = iptables.ensureRule(utiliptables.RulePosition(rule[0]), utiliptables.TableNAT, utiliptables.Chain(rule[1]), rule[2]) - assert.NoError(t, err) - - writeLine(natRules, utiliptables.MakeChainLine(utiliptables.Chain(rule[1]))) - } - writeLine(natRules, "COMMIT") - assert.NoError(t, iptables.Restore(utiliptables.TableNAT, natRules.Bytes(), utiliptables.NoFlushTables, utiliptables.RestoreCounters)) - natTable, ok := iptables.tables[string(utiliptables.TableNAT)] - assert.True(t, ok) - // check KUBE-HOSTPORTS chain, should have been cleaned up - hostportChain, ok := natTable.chains["KUBE-HOSTPORTS"] - assert.True(t, ok) - assert.Equal(t, 0, len(hostportChain.rules)) - - // check builtin chains, should not been cleaned up - postroutingChain, ok := natTable.chains["POSTROUTING"] - assert.True(t, ok, string(postroutingChain.name)) - assert.Equal(t, 1, len(postroutingChain.rules)) -} diff --git a/pkg/kubelet/dockershim/network/hostport/hostport.go b/pkg/kubelet/dockershim/network/hostport/hostport.go deleted file mode 100644 index cb68abdc017..00000000000 --- a/pkg/kubelet/dockershim/network/hostport/hostport.go +++ /dev/null @@ -1,171 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hostport - -import ( - "fmt" - "net" - "strconv" - "strings" - - "k8s.io/klog/v2" - - v1 "k8s.io/api/core/v1" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" -) - -const ( - // the hostport chain - kubeHostportsChain utiliptables.Chain = "KUBE-HOSTPORTS" - // prefix for hostport chains - kubeHostportChainPrefix string = "KUBE-HP-" -) - -// PortMapping represents a network port in a container -type PortMapping struct { - HostPort int32 - ContainerPort int32 - Protocol v1.Protocol - HostIP string -} - -// PodPortMapping represents a pod's network state and associated container port mappings -type PodPortMapping struct { - Namespace string - Name string - PortMappings []*PortMapping - HostNetwork bool - IP net.IP -} - -// ipFamily refers to a specific family if not empty, i.e. "4" or "6". -type ipFamily string - -// Constants for valid IPFamily: -const ( - IPv4 ipFamily = "4" - IPv6 ipFamily = "6" -) - -type hostport struct { - ipFamily ipFamily - ip string - port int32 - protocol string -} - -type hostportOpener func(*hostport) (closeable, error) - -type closeable interface { - Close() error -} - -func openLocalPort(hp *hostport) (closeable, error) { - // For ports on node IPs, open the actual port and hold it, even though we - // use iptables to redirect traffic. - // This ensures a) that it's safe to use that port and b) that (a) stays - // true. The risk is that some process on the node (e.g. sshd or kubelet) - // is using a port and we give that same port out to a Service. That would - // be bad because iptables would silently claim the traffic but the process - // would never know. - // NOTE: We should not need to have a real listen()ing socket - bind() - // should be enough, but I can't figure out a way to e2e test without - // it. Tools like 'ss' and 'netstat' do not show sockets that are - // bind()ed but not listen()ed, and at least the default debian netcat - // has no way to avoid about 10 seconds of retries. - var socket closeable - // open the socket on the HostIP and HostPort specified - address := net.JoinHostPort(hp.ip, strconv.Itoa(int(hp.port))) - switch hp.protocol { - case "tcp": - network := "tcp" + string(hp.ipFamily) - listener, err := net.Listen(network, address) - if err != nil { - return nil, err - } - socket = listener - case "udp": - network := "udp" + string(hp.ipFamily) - addr, err := net.ResolveUDPAddr(network, address) - if err != nil { - return nil, err - } - conn, err := net.ListenUDP(network, addr) - if err != nil { - return nil, err - } - socket = conn - default: - return nil, fmt.Errorf("unknown protocol %q", hp.protocol) - } - klog.V(3).InfoS("Opened local port", "port", hp.String()) - return socket, nil -} - -// portMappingToHostport creates hostport structure based on input portmapping -func portMappingToHostport(portMapping *PortMapping, family ipFamily) hostport { - return hostport{ - ipFamily: family, - ip: portMapping.HostIP, - port: portMapping.HostPort, - protocol: strings.ToLower(string(portMapping.Protocol)), - } -} - -// ensureKubeHostportChains ensures the KUBE-HOSTPORTS chain is setup correctly -func ensureKubeHostportChains(iptables utiliptables.Interface, natInterfaceName string) error { - klog.V(4).InfoS("Ensuring kubelet hostport chains") - // Ensure kubeHostportChain - if _, err := iptables.EnsureChain(utiliptables.TableNAT, kubeHostportsChain); err != nil { - return fmt.Errorf("failed to ensure that %s chain %s exists: %v", utiliptables.TableNAT, kubeHostportsChain, err) - } - tableChainsNeedJumpServices := []struct { - table utiliptables.Table - chain utiliptables.Chain - }{ - {utiliptables.TableNAT, utiliptables.ChainOutput}, - {utiliptables.TableNAT, utiliptables.ChainPrerouting}, - } - args := []string{ - "-m", "comment", "--comment", "kube hostport portals", - "-m", "addrtype", "--dst-type", "LOCAL", - "-j", string(kubeHostportsChain), - } - for _, tc := range tableChainsNeedJumpServices { - // KUBE-HOSTPORTS chain needs to be appended to the system chains. - // This ensures KUBE-SERVICES chain gets processed first. - // Since rules in KUBE-HOSTPORTS chain matches broader cases, allow the more specific rules to be processed first. - if _, err := iptables.EnsureRule(utiliptables.Append, tc.table, tc.chain, args...); err != nil { - return fmt.Errorf("failed to ensure that %s chain %s jumps to %s: %v", tc.table, tc.chain, kubeHostportsChain, err) - } - } - if natInterfaceName != "" && natInterfaceName != "lo" { - // Need to SNAT traffic from localhost - localhost := "127.0.0.0/8" - if iptables.IsIPv6() { - localhost = "::1/128" - } - args = []string{"-m", "comment", "--comment", "SNAT for localhost access to hostports", "-o", natInterfaceName, "-s", localhost, "-j", "MASQUERADE"} - if _, err := iptables.EnsureRule(utiliptables.Append, utiliptables.TableNAT, utiliptables.ChainPostrouting, args...); err != nil { - return fmt.Errorf("failed to ensure that %s chain %s jumps to MASQUERADE: %v", utiliptables.TableNAT, utiliptables.ChainPostrouting, err) - } - } - return nil -} diff --git a/pkg/kubelet/dockershim/network/hostport/hostport_manager.go b/pkg/kubelet/dockershim/network/hostport/hostport_manager.go deleted file mode 100644 index 3caa2007b62..00000000000 --- a/pkg/kubelet/dockershim/network/hostport/hostport_manager.go +++ /dev/null @@ -1,445 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hostport - -import ( - "bytes" - "crypto/sha256" - "encoding/base32" - "fmt" - "net" - "strconv" - "strings" - "sync" - - v1 "k8s.io/api/core/v1" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/klog/v2" - iptablesproxy "k8s.io/kubernetes/pkg/proxy/iptables" - "k8s.io/kubernetes/pkg/util/conntrack" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" - "k8s.io/utils/exec" - utilnet "k8s.io/utils/net" -) - -// HostPortManager is an interface for adding and removing hostport for a given pod sandbox. -type HostPortManager interface { - // Add implements port mappings. - // id should be a unique identifier for a pod, e.g. podSandboxID. - // podPortMapping is the associated port mapping information for the pod. - // natInterfaceName is the interface that localhost uses to talk to the given pod, if known. - Add(id string, podPortMapping *PodPortMapping, natInterfaceName string) error - // Remove cleans up matching port mappings - // Remove must be able to clean up port mappings without pod IP - Remove(id string, podPortMapping *PodPortMapping) error -} - -type hostportManager struct { - hostPortMap map[hostport]closeable - execer exec.Interface - conntrackFound bool - iptables utiliptables.Interface - portOpener hostportOpener - mu sync.Mutex -} - -// NewHostportManager creates a new HostPortManager -func NewHostportManager(iptables utiliptables.Interface) HostPortManager { - h := &hostportManager{ - hostPortMap: make(map[hostport]closeable), - execer: exec.New(), - iptables: iptables, - portOpener: openLocalPort, - } - h.conntrackFound = conntrack.Exists(h.execer) - if !h.conntrackFound { - klog.InfoS("The binary conntrack is not installed, this can cause failures in network connection cleanup.") - } - return h -} - -func (hm *hostportManager) Add(id string, podPortMapping *PodPortMapping, natInterfaceName string) (err error) { - if podPortMapping == nil || podPortMapping.HostNetwork { - return nil - } - podFullName := getPodFullName(podPortMapping) - // IP.To16() returns nil if IP is not a valid IPv4 or IPv6 address - if podPortMapping.IP.To16() == nil { - return fmt.Errorf("invalid or missing IP of pod %s", podFullName) - } - podIP := podPortMapping.IP.String() - isIPv6 := utilnet.IsIPv6(podPortMapping.IP) - - // skip if there is no hostport needed - hostportMappings := gatherHostportMappings(podPortMapping, isIPv6) - if len(hostportMappings) == 0 { - return nil - } - - if isIPv6 != hm.iptables.IsIPv6() { - return fmt.Errorf("HostPortManager IP family mismatch: %v, isIPv6 - %v", podIP, isIPv6) - } - - if err := ensureKubeHostportChains(hm.iptables, natInterfaceName); err != nil { - return err - } - - // Ensure atomicity for port opening and iptables operations - hm.mu.Lock() - defer hm.mu.Unlock() - - // try to open hostports - ports, err := hm.openHostports(podPortMapping) - if err != nil { - return err - } - for hostport, socket := range ports { - hm.hostPortMap[hostport] = socket - } - - natChains := bytes.NewBuffer(nil) - natRules := bytes.NewBuffer(nil) - writeLine(natChains, "*nat") - - existingChains, existingRules, err := getExistingHostportIPTablesRules(hm.iptables) - if err != nil { - // clean up opened host port if encounter any error - return utilerrors.NewAggregate([]error{err, hm.closeHostports(hostportMappings)}) - } - - newChains := []utiliptables.Chain{} - conntrackPortsToRemove := []int{} - for _, pm := range hostportMappings { - protocol := strings.ToLower(string(pm.Protocol)) - chain := getHostportChain(id, pm) - newChains = append(newChains, chain) - if pm.Protocol == v1.ProtocolUDP { - conntrackPortsToRemove = append(conntrackPortsToRemove, int(pm.HostPort)) - } - - // Add new hostport chain - writeLine(natChains, utiliptables.MakeChainLine(chain)) - - // Prepend the new chain to KUBE-HOSTPORTS - // This avoids any leaking iptables rule that takes up the same port - writeLine(natRules, "-I", string(kubeHostportsChain), - "-m", "comment", "--comment", fmt.Sprintf(`"%s hostport %d"`, podFullName, pm.HostPort), - "-m", protocol, "-p", protocol, "--dport", fmt.Sprintf("%d", pm.HostPort), - "-j", string(chain), - ) - - // SNAT if the traffic comes from the pod itself - writeLine(natRules, "-A", string(chain), - "-m", "comment", "--comment", fmt.Sprintf(`"%s hostport %d"`, podFullName, pm.HostPort), - "-s", podIP, - "-j", string(iptablesproxy.KubeMarkMasqChain)) - - // DNAT to the podIP:containerPort - hostPortBinding := net.JoinHostPort(podIP, strconv.Itoa(int(pm.ContainerPort))) - if pm.HostIP == "" || pm.HostIP == "0.0.0.0" || pm.HostIP == "::" { - writeLine(natRules, "-A", string(chain), - "-m", "comment", "--comment", fmt.Sprintf(`"%s hostport %d"`, podFullName, pm.HostPort), - "-m", protocol, "-p", protocol, - "-j", "DNAT", fmt.Sprintf("--to-destination=%s", hostPortBinding)) - } else { - writeLine(natRules, "-A", string(chain), - "-m", "comment", "--comment", fmt.Sprintf(`"%s hostport %d"`, podFullName, pm.HostPort), - "-m", protocol, "-p", protocol, "-d", pm.HostIP, - "-j", "DNAT", fmt.Sprintf("--to-destination=%s", hostPortBinding)) - } - } - - // getHostportChain should be able to provide unique hostport chain name using hash - // if there is a chain conflict or multiple Adds have been triggered for a single pod, - // filtering should be able to avoid further problem - filterChains(existingChains, newChains) - existingRules = filterRules(existingRules, newChains) - - for _, chain := range existingChains { - writeLine(natChains, chain) - } - for _, rule := range existingRules { - writeLine(natRules, rule) - } - writeLine(natRules, "COMMIT") - - if err = hm.syncIPTables(append(natChains.Bytes(), natRules.Bytes()...)); err != nil { - // clean up opened host port if encounter any error - return utilerrors.NewAggregate([]error{err, hm.closeHostports(hostportMappings)}) - } - - // Remove conntrack entries just after adding the new iptables rules. If the conntrack entry is removed along with - // the IP tables rule, it can be the case that the packets received by the node after iptables rule removal will - // create a new conntrack entry without any DNAT. That will result in blackhole of the traffic even after correct - // iptables rules have been added back. - if hm.execer != nil && hm.conntrackFound { - klog.InfoS("Starting to delete udp conntrack entries", "conntrackEntries", conntrackPortsToRemove, "isIPv6", isIPv6) - for _, port := range conntrackPortsToRemove { - err = conntrack.ClearEntriesForPort(hm.execer, port, isIPv6, v1.ProtocolUDP) - if err != nil { - klog.ErrorS(err, "Failed to clear udp conntrack for port", "port", port) - } - } - } - return nil -} - -func (hm *hostportManager) Remove(id string, podPortMapping *PodPortMapping) (err error) { - if podPortMapping == nil || podPortMapping.HostNetwork { - return nil - } - - hostportMappings := gatherHostportMappings(podPortMapping, hm.iptables.IsIPv6()) - if len(hostportMappings) == 0 { - return nil - } - - // Ensure atomicity for port closing and iptables operations - hm.mu.Lock() - defer hm.mu.Unlock() - - var existingChains map[utiliptables.Chain]string - var existingRules []string - existingChains, existingRules, err = getExistingHostportIPTablesRules(hm.iptables) - if err != nil { - return err - } - - // Gather target hostport chains for removal - chainsToRemove := []utiliptables.Chain{} - for _, pm := range hostportMappings { - chainsToRemove = append(chainsToRemove, getHostportChain(id, pm)) - } - - // remove rules that consists of target chains - remainingRules := filterRules(existingRules, chainsToRemove) - - // gather target hostport chains that exists in iptables-save result - existingChainsToRemove := []utiliptables.Chain{} - for _, chain := range chainsToRemove { - if _, ok := existingChains[chain]; ok { - existingChainsToRemove = append(existingChainsToRemove, chain) - } - } - - // exit if there is nothing to remove - // don´t forget to clean up opened pod host ports - if len(existingChainsToRemove) == 0 { - return hm.closeHostports(hostportMappings) - } - - natChains := bytes.NewBuffer(nil) - natRules := bytes.NewBuffer(nil) - writeLine(natChains, "*nat") - for _, chain := range existingChains { - writeLine(natChains, chain) - } - for _, rule := range remainingRules { - writeLine(natRules, rule) - } - for _, chain := range existingChainsToRemove { - writeLine(natRules, "-X", string(chain)) - } - writeLine(natRules, "COMMIT") - - if err := hm.syncIPTables(append(natChains.Bytes(), natRules.Bytes()...)); err != nil { - return err - } - - // clean up opened pod host ports - return hm.closeHostports(hostportMappings) -} - -// syncIPTables executes iptables-restore with given lines -func (hm *hostportManager) syncIPTables(lines []byte) error { - klog.V(3).InfoS("Restoring iptables rules", "iptableRules", lines) - err := hm.iptables.RestoreAll(lines, utiliptables.NoFlushTables, utiliptables.RestoreCounters) - if err != nil { - return fmt.Errorf("failed to execute iptables-restore: %v", err) - } - return nil -} - -// openHostports opens all given hostports using the given hostportOpener -// If encounter any error, clean up and return the error -// If all ports are opened successfully, return the hostport and socket mapping -func (hm *hostportManager) openHostports(podPortMapping *PodPortMapping) (map[hostport]closeable, error) { - var retErr error - ports := make(map[hostport]closeable) - for _, pm := range podPortMapping.PortMappings { - if pm.HostPort <= 0 { - continue - } - - // We do not open host ports for SCTP ports, as we agreed in the Support of SCTP KEP - if pm.Protocol == v1.ProtocolSCTP { - continue - } - - // HostIP IP family is not handled by this port opener - if pm.HostIP != "" && utilnet.IsIPv6String(pm.HostIP) != hm.iptables.IsIPv6() { - continue - } - - hp := portMappingToHostport(pm, hm.getIPFamily()) - socket, err := hm.portOpener(&hp) - if err != nil { - retErr = fmt.Errorf("cannot open hostport %d for pod %s: %v", pm.HostPort, getPodFullName(podPortMapping), err) - break - } - ports[hp] = socket - } - - // If encounter any error, close all hostports that just got opened. - if retErr != nil { - for hp, socket := range ports { - if err := socket.Close(); err != nil { - klog.ErrorS(err, "Cannot clean up hostport for the pod", "podFullName", getPodFullName(podPortMapping), "port", hp.port) - } - } - return nil, retErr - } - return ports, nil -} - -// closeHostports tries to close all the listed host ports -func (hm *hostportManager) closeHostports(hostportMappings []*PortMapping) error { - errList := []error{} - for _, pm := range hostportMappings { - hp := portMappingToHostport(pm, hm.getIPFamily()) - if socket, ok := hm.hostPortMap[hp]; ok { - klog.V(2).InfoS("Closing host port", "port", hp.String()) - if err := socket.Close(); err != nil { - errList = append(errList, fmt.Errorf("failed to close host port %s: %v", hp.String(), err)) - continue - } - delete(hm.hostPortMap, hp) - } else { - klog.V(5).InfoS("Host port does not have an open socket", "port", hp.String()) - } - } - return utilerrors.NewAggregate(errList) -} - -// getIPFamily returns the hostPortManager IP family -func (hm *hostportManager) getIPFamily() ipFamily { - family := IPv4 - if hm.iptables.IsIPv6() { - family = IPv6 - } - return family -} - -// getHostportChain takes id, hostport and protocol for a pod and returns associated iptables chain. -// This is computed by hashing (sha256) then encoding to base32 and truncating with the prefix -// "KUBE-HP-". We do this because IPTables Chain Names must be <= 28 chars long, and the longer -// they are the harder they are to read. -// WARNING: Please do not change this function. Otherwise, HostportManager may not be able to -// identify existing iptables chains. -func getHostportChain(id string, pm *PortMapping) utiliptables.Chain { - hash := sha256.Sum256([]byte(id + strconv.Itoa(int(pm.HostPort)) + string(pm.Protocol) + pm.HostIP)) - encoded := base32.StdEncoding.EncodeToString(hash[:]) - return utiliptables.Chain(kubeHostportChainPrefix + encoded[:16]) -} - -// gatherHostportMappings returns all the PortMappings which has hostport for a pod -// it filters the PortMappings that use HostIP and doesn't match the IP family specified -func gatherHostportMappings(podPortMapping *PodPortMapping, isIPv6 bool) []*PortMapping { - mappings := []*PortMapping{} - for _, pm := range podPortMapping.PortMappings { - if pm.HostPort <= 0 { - continue - } - if pm.HostIP != "" && utilnet.IsIPv6String(pm.HostIP) != isIPv6 { - continue - } - mappings = append(mappings, pm) - } - return mappings -} - -// getExistingHostportIPTablesRules retrieves raw data from iptables-save, parse it, -// return all the hostport related chains and rules -func getExistingHostportIPTablesRules(iptables utiliptables.Interface) (map[utiliptables.Chain]string, []string, error) { - iptablesData := bytes.NewBuffer(nil) - err := iptables.SaveInto(utiliptables.TableNAT, iptablesData) - if err != nil { // if we failed to get any rules - return nil, nil, fmt.Errorf("failed to execute iptables-save: %v", err) - } - existingNATChains := utiliptables.GetChainLines(utiliptables.TableNAT, iptablesData.Bytes()) - - existingHostportChains := make(map[utiliptables.Chain]string) - existingHostportRules := []string{} - - for chain := range existingNATChains { - if strings.HasPrefix(string(chain), string(kubeHostportsChain)) || strings.HasPrefix(string(chain), kubeHostportChainPrefix) { - existingHostportChains[chain] = string(existingNATChains[chain]) - } - } - - for _, line := range strings.Split(iptablesData.String(), "\n") { - if strings.HasPrefix(line, fmt.Sprintf("-A %s", kubeHostportChainPrefix)) || - strings.HasPrefix(line, fmt.Sprintf("-A %s", string(kubeHostportsChain))) { - existingHostportRules = append(existingHostportRules, line) - } - } - return existingHostportChains, existingHostportRules, nil -} - -// filterRules filters input rules with input chains. Rules that did not involve any filter chain will be returned. -// The order of the input rules is important and is preserved. -func filterRules(rules []string, filters []utiliptables.Chain) []string { - filtered := []string{} - for _, rule := range rules { - skip := false - for _, filter := range filters { - if strings.Contains(rule, string(filter)) { - skip = true - break - } - } - if !skip { - filtered = append(filtered, rule) - } - } - return filtered -} - -// filterChains deletes all entries of filter chains from chain map -func filterChains(chains map[utiliptables.Chain]string, filterChains []utiliptables.Chain) { - for _, chain := range filterChains { - delete(chains, chain) - } -} - -func getPodFullName(pod *PodPortMapping) string { - // Use underscore as the delimiter because it is not allowed in pod name - // (DNS subdomain format), while allowed in the container name format. - return pod.Name + "_" + pod.Namespace -} - -// Join all words with spaces, terminate with newline and write to buf. -func writeLine(buf *bytes.Buffer, words ...string) { - buf.WriteString(strings.Join(words, " ") + "\n") -} - -func (hp *hostport) String() string { - return fmt.Sprintf("%s:%d", hp.protocol, hp.port) -} diff --git a/pkg/kubelet/dockershim/network/hostport/hostport_manager_test.go b/pkg/kubelet/dockershim/network/hostport/hostport_manager_test.go deleted file mode 100644 index 1f0046a17a9..00000000000 --- a/pkg/kubelet/dockershim/network/hostport/hostport_manager_test.go +++ /dev/null @@ -1,734 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hostport - -import ( - "bytes" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" - "k8s.io/utils/exec" - netutils "k8s.io/utils/net" -) - -func TestOpenCloseHostports(t *testing.T) { - openPortCases := []struct { - podPortMapping *PodPortMapping - expectError bool - }{ - // no portmaps - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n0", - }, - false, - }, - // allocate port 80/TCP, 8080/TCP and 443/TCP - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n1", - PortMappings: []*PortMapping{ - {HostPort: 80, Protocol: v1.ProtocolTCP}, - {HostPort: 8080, Protocol: v1.ProtocolTCP}, - {HostPort: 443, Protocol: v1.ProtocolTCP}, - }, - }, - false, - }, - // fail to allocate port previously allocated 80/TCP - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n2", - PortMappings: []*PortMapping{ - {HostPort: 80, Protocol: v1.ProtocolTCP}, - }, - }, - true, - }, - // fail to allocate port previously allocated 8080/TCP - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n3", - PortMappings: []*PortMapping{ - {HostPort: 8081, Protocol: v1.ProtocolTCP}, - {HostPort: 8080, Protocol: v1.ProtocolTCP}, - }, - }, - true, - }, - // allocate port 8081/TCP - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n3", - PortMappings: []*PortMapping{ - {HostPort: 8081, Protocol: v1.ProtocolTCP}, - }, - }, - false, - }, - // allocate port 7777/SCTP - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n4", - PortMappings: []*PortMapping{ - {HostPort: 7777, Protocol: v1.ProtocolSCTP}, - }, - }, - false, - }, - // same HostPort different HostIP - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n5", - PortMappings: []*PortMapping{ - {HostPort: 8888, Protocol: v1.ProtocolUDP, HostIP: "127.0.0.1"}, - {HostPort: 8888, Protocol: v1.ProtocolUDP, HostIP: "127.0.0.2"}, - }, - }, - false, - }, - // same HostPort different protocol - { - &PodPortMapping{ - Namespace: "ns1", - Name: "n6", - PortMappings: []*PortMapping{ - {HostPort: 9999, Protocol: v1.ProtocolTCP}, - {HostPort: 9999, Protocol: v1.ProtocolUDP}, - }, - }, - false, - }, - } - - iptables := NewFakeIPTables() - iptables.protocol = utiliptables.ProtocolIPv4 - portOpener := NewFakeSocketManager() - manager := &hostportManager{ - hostPortMap: make(map[hostport]closeable), - iptables: iptables, - portOpener: portOpener.openFakeSocket, - execer: exec.New(), - } - - // open all hostports defined in the test cases - for _, tc := range openPortCases { - mapping, err := manager.openHostports(tc.podPortMapping) - for hostport, socket := range mapping { - manager.hostPortMap[hostport] = socket - } - if tc.expectError { - assert.Error(t, err) - continue - } - assert.NoError(t, err) - // SCTP ports are not allocated - countSctp := 0 - for _, pm := range tc.podPortMapping.PortMappings { - if pm.Protocol == v1.ProtocolSCTP { - countSctp++ - } - } - assert.EqualValues(t, len(mapping), len(tc.podPortMapping.PortMappings)-countSctp) - } - - // We have following ports open: 80/TCP, 443/TCP, 8080/TCP, 8081/TCP, - // 127.0.0.1:8888/TCP, 127.0.0.2:8888/TCP, 9999/TCP and 9999/UDP open now. - assert.EqualValues(t, len(manager.hostPortMap), 8) - closePortCases := []struct { - portMappings []*PortMapping - expectError bool - }{ - { - portMappings: nil, - }, - { - - portMappings: []*PortMapping{ - {HostPort: 80, Protocol: v1.ProtocolTCP}, - {HostPort: 8080, Protocol: v1.ProtocolTCP}, - {HostPort: 443, Protocol: v1.ProtocolTCP}, - }, - }, - { - - portMappings: []*PortMapping{ - {HostPort: 80, Protocol: v1.ProtocolTCP}, - }, - }, - { - portMappings: []*PortMapping{ - {HostPort: 8081, Protocol: v1.ProtocolTCP}, - {HostPort: 8080, Protocol: v1.ProtocolTCP}, - }, - }, - { - portMappings: []*PortMapping{ - {HostPort: 8081, Protocol: v1.ProtocolTCP}, - }, - }, - { - portMappings: []*PortMapping{ - {HostPort: 7070, Protocol: v1.ProtocolTCP}, - }, - }, - { - portMappings: []*PortMapping{ - {HostPort: 7777, Protocol: v1.ProtocolSCTP}, - }, - }, - { - portMappings: []*PortMapping{ - {HostPort: 8888, Protocol: v1.ProtocolUDP, HostIP: "127.0.0.1"}, - {HostPort: 8888, Protocol: v1.ProtocolUDP, HostIP: "127.0.0.2"}, - }, - }, - { - portMappings: []*PortMapping{ - {HostPort: 9999, Protocol: v1.ProtocolTCP}, - {HostPort: 9999, Protocol: v1.ProtocolUDP}, - }, - }, - } - - // close all the hostports opened in previous step - for _, tc := range closePortCases { - err := manager.closeHostports(tc.portMappings) - if tc.expectError { - assert.Error(t, err) - continue - } - assert.NoError(t, err) - } - // assert all elements in hostPortMap were cleared - assert.Zero(t, len(manager.hostPortMap)) -} - -func TestHostportManager(t *testing.T) { - iptables := NewFakeIPTables() - iptables.protocol = utiliptables.ProtocolIPv4 - portOpener := NewFakeSocketManager() - manager := &hostportManager{ - hostPortMap: make(map[hostport]closeable), - iptables: iptables, - portOpener: portOpener.openFakeSocket, - execer: exec.New(), - } - testCases := []struct { - mapping *PodPortMapping - expectError bool - }{ - // open HostPorts 8080/TCP, 8081/UDP and 8083/SCTP - { - mapping: &PodPortMapping{ - Name: "pod1", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("10.1.1.2"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8080, - ContainerPort: 80, - Protocol: v1.ProtocolTCP, - }, - { - HostPort: 8081, - ContainerPort: 81, - Protocol: v1.ProtocolUDP, - }, - { - HostPort: 8083, - ContainerPort: 83, - Protocol: v1.ProtocolSCTP, - }, - }, - }, - expectError: false, - }, - // fail to open HostPort due to conflict 8083/SCTP - { - mapping: &PodPortMapping{ - Name: "pod2", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("10.1.1.3"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8082, - ContainerPort: 80, - Protocol: v1.ProtocolTCP, - }, - { - HostPort: 8081, - ContainerPort: 81, - Protocol: v1.ProtocolUDP, - }, - { - HostPort: 8083, - ContainerPort: 83, - Protocol: v1.ProtocolSCTP, - }, - }, - }, - expectError: true, - }, - // open port 443 - { - mapping: &PodPortMapping{ - Name: "pod3", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("10.1.1.4"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8443, - ContainerPort: 443, - Protocol: v1.ProtocolTCP, - }, - }, - }, - expectError: false, - }, - // fail to open HostPort 8443 already allocated - { - mapping: &PodPortMapping{ - Name: "pod3", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("192.168.12.12"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8443, - ContainerPort: 443, - Protocol: v1.ProtocolTCP, - }, - }, - }, - expectError: true, - }, - // skip HostPort with PodIP and HostIP using different families - { - mapping: &PodPortMapping{ - Name: "pod4", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("2001:beef::2"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8444, - ContainerPort: 444, - Protocol: v1.ProtocolTCP, - HostIP: "192.168.1.1", - }, - }, - }, - expectError: false, - }, - - // open same HostPort on different IP - { - mapping: &PodPortMapping{ - Name: "pod5", - Namespace: "ns5", - IP: netutils.ParseIPSloppy("10.1.1.5"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8888, - ContainerPort: 443, - Protocol: v1.ProtocolTCP, - HostIP: "127.0.0.2", - }, - { - HostPort: 8888, - ContainerPort: 443, - Protocol: v1.ProtocolTCP, - HostIP: "127.0.0.1", - }, - }, - }, - expectError: false, - }, - // open same HostPort on different - { - mapping: &PodPortMapping{ - Name: "pod6", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("10.1.1.2"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 9999, - ContainerPort: 443, - Protocol: v1.ProtocolTCP, - }, - { - HostPort: 9999, - ContainerPort: 443, - Protocol: v1.ProtocolUDP, - }, - }, - }, - expectError: false, - }, - } - - // Add Hostports - for _, tc := range testCases { - err := manager.Add("id", tc.mapping, "cbr0") - if tc.expectError { - assert.Error(t, err) - continue - } - assert.NoError(t, err) - } - - // Check port opened - expectedPorts := []hostport{ - {IPv4, "", 8080, "tcp"}, - {IPv4, "", 8081, "udp"}, - {IPv4, "", 8443, "tcp"}, - {IPv4, "127.0.0.1", 8888, "tcp"}, - {IPv4, "127.0.0.2", 8888, "tcp"}, - {IPv4, "", 9999, "tcp"}, - {IPv4, "", 9999, "udp"}, - } - openedPorts := make(map[hostport]bool) - for hp, port := range portOpener.mem { - if !port.closed { - openedPorts[hp] = true - } - } - assert.EqualValues(t, len(openedPorts), len(expectedPorts)) - for _, hp := range expectedPorts { - _, ok := openedPorts[hp] - assert.EqualValues(t, true, ok) - } - - // Check Iptables-save result after adding hostports - raw := bytes.NewBuffer(nil) - err := iptables.SaveInto(utiliptables.TableNAT, raw) - assert.NoError(t, err) - - lines := strings.Split(raw.String(), "\n") - expectedLines := map[string]bool{ - `*nat`: true, - `:KUBE-HOSTPORTS - [0:0]`: true, - `:OUTPUT - [0:0]`: true, - `:PREROUTING - [0:0]`: true, - `:POSTROUTING - [0:0]`: true, - `:KUBE-HP-IJHALPHTORMHHPPK - [0:0]`: true, - `:KUBE-HP-63UPIDJXVRSZGSUZ - [0:0]`: true, - `:KUBE-HP-WFBOALXEP42XEMJK - [0:0]`: true, - `:KUBE-HP-XU6AWMMJYOZOFTFZ - [0:0]`: true, - `:KUBE-HP-TUKTZ736U5JD5UTK - [0:0]`: true, - `:KUBE-HP-CAAJ45HDITK7ARGM - [0:0]`: true, - `:KUBE-HP-WFUNFVXVDLD5ZVXN - [0:0]`: true, - `:KUBE-HP-4MFWH2F2NAOMYD6A - [0:0]`: true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp --dport 8443 -j KUBE-HP-WFBOALXEP42XEMJK": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8081\" -m udp -p udp --dport 8081 -j KUBE-HP-63UPIDJXVRSZGSUZ": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8080\" -m tcp -p tcp --dport 8080 -j KUBE-HP-IJHALPHTORMHHPPK": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8083\" -m sctp -p sctp --dport 8083 -j KUBE-HP-XU6AWMMJYOZOFTFZ": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod5_ns5 hostport 8888\" -m tcp -p tcp --dport 8888 -j KUBE-HP-TUKTZ736U5JD5UTK": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod5_ns5 hostport 8888\" -m tcp -p tcp --dport 8888 -j KUBE-HP-CAAJ45HDITK7ARGM": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod6_ns1 hostport 9999\" -m udp -p udp --dport 9999 -j KUBE-HP-4MFWH2F2NAOMYD6A": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod6_ns1 hostport 9999\" -m tcp -p tcp --dport 9999 -j KUBE-HP-WFUNFVXVDLD5ZVXN": true, - "-A OUTPUT -m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS": true, - "-A PREROUTING -m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS": true, - "-A POSTROUTING -m comment --comment \"SNAT for localhost access to hostports\" -o cbr0 -s 127.0.0.0/8 -j MASQUERADE": true, - "-A KUBE-HP-IJHALPHTORMHHPPK -m comment --comment \"pod1_ns1 hostport 8080\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-IJHALPHTORMHHPPK -m comment --comment \"pod1_ns1 hostport 8080\" -m tcp -p tcp -j DNAT --to-destination 10.1.1.2:80": true, - "-A KUBE-HP-63UPIDJXVRSZGSUZ -m comment --comment \"pod1_ns1 hostport 8081\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-63UPIDJXVRSZGSUZ -m comment --comment \"pod1_ns1 hostport 8081\" -m udp -p udp -j DNAT --to-destination 10.1.1.2:81": true, - "-A KUBE-HP-XU6AWMMJYOZOFTFZ -m comment --comment \"pod1_ns1 hostport 8083\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-XU6AWMMJYOZOFTFZ -m comment --comment \"pod1_ns1 hostport 8083\" -m sctp -p sctp -j DNAT --to-destination 10.1.1.2:83": true, - "-A KUBE-HP-WFBOALXEP42XEMJK -m comment --comment \"pod3_ns1 hostport 8443\" -s 10.1.1.4/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-WFBOALXEP42XEMJK -m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp -j DNAT --to-destination 10.1.1.4:443": true, - "-A KUBE-HP-TUKTZ736U5JD5UTK -m comment --comment \"pod5_ns5 hostport 8888\" -s 10.1.1.5/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-TUKTZ736U5JD5UTK -m comment --comment \"pod5_ns5 hostport 8888\" -m tcp -p tcp -d 127.0.0.1/32 -j DNAT --to-destination 10.1.1.5:443": true, - "-A KUBE-HP-CAAJ45HDITK7ARGM -m comment --comment \"pod5_ns5 hostport 8888\" -s 10.1.1.5/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-CAAJ45HDITK7ARGM -m comment --comment \"pod5_ns5 hostport 8888\" -m tcp -p tcp -d 127.0.0.2/32 -j DNAT --to-destination 10.1.1.5:443": true, - "-A KUBE-HP-WFUNFVXVDLD5ZVXN -m comment --comment \"pod6_ns1 hostport 9999\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-WFUNFVXVDLD5ZVXN -m comment --comment \"pod6_ns1 hostport 9999\" -m tcp -p tcp -j DNAT --to-destination 10.1.1.2:443": true, - "-A KUBE-HP-4MFWH2F2NAOMYD6A -m comment --comment \"pod6_ns1 hostport 9999\" -s 10.1.1.2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-4MFWH2F2NAOMYD6A -m comment --comment \"pod6_ns1 hostport 9999\" -m udp -p udp -j DNAT --to-destination 10.1.1.2:443": true, - `COMMIT`: true, - } - for _, line := range lines { - t.Logf("Line: %s", line) - if len(strings.TrimSpace(line)) > 0 { - _, ok := expectedLines[strings.TrimSpace(line)] - assert.EqualValues(t, true, ok) - } - } - - // Remove all added hostports - for _, tc := range testCases { - if !tc.expectError { - err := manager.Remove("id", tc.mapping) - assert.NoError(t, err) - } - } - - // Check Iptables-save result after deleting hostports - raw.Reset() - err = iptables.SaveInto(utiliptables.TableNAT, raw) - assert.NoError(t, err) - lines = strings.Split(raw.String(), "\n") - remainingChains := make(map[string]bool) - for _, line := range lines { - if strings.HasPrefix(line, ":") { - remainingChains[strings.TrimSpace(line)] = true - } - } - expectDeletedChains := []string{ - "KUBE-HP-4YVONL46AKYWSKS3", "KUBE-HP-7THKRFSEH4GIIXK7", "KUBE-HP-5N7UH5JAXCVP5UJR", - "KUBE-HP-TUKTZ736U5JD5UTK", "KUBE-HP-CAAJ45HDITK7ARGM", "KUBE-HP-WFUNFVXVDLD5ZVXN", "KUBE-HP-4MFWH2F2NAOMYD6A", - } - for _, chain := range expectDeletedChains { - _, ok := remainingChains[chain] - assert.EqualValues(t, false, ok) - } - - // check if all ports are closed - for _, port := range portOpener.mem { - assert.EqualValues(t, true, port.closed) - } - // Clear all elements in hostPortMap - assert.Zero(t, len(manager.hostPortMap)) -} - -func TestGetHostportChain(t *testing.T) { - m := make(map[string]int) - chain := getHostportChain("testrdma-2", &PortMapping{HostPort: 57119, Protocol: "TCP", ContainerPort: 57119}) - m[string(chain)] = 1 - chain = getHostportChain("testrdma-2", &PortMapping{HostPort: 55429, Protocol: "TCP", ContainerPort: 55429}) - m[string(chain)] = 1 - chain = getHostportChain("testrdma-2", &PortMapping{HostPort: 56833, Protocol: "TCP", ContainerPort: 56833}) - m[string(chain)] = 1 - if len(m) != 3 { - t.Fatal(m) - } -} - -func TestHostportManagerIPv6(t *testing.T) { - iptables := NewFakeIPTables() - iptables.protocol = utiliptables.ProtocolIPv6 - portOpener := NewFakeSocketManager() - manager := &hostportManager{ - hostPortMap: make(map[hostport]closeable), - iptables: iptables, - portOpener: portOpener.openFakeSocket, - execer: exec.New(), - } - testCases := []struct { - mapping *PodPortMapping - expectError bool - }{ - { - mapping: &PodPortMapping{ - Name: "pod1", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("2001:beef::2"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8080, - ContainerPort: 80, - Protocol: v1.ProtocolTCP, - }, - { - HostPort: 8081, - ContainerPort: 81, - Protocol: v1.ProtocolUDP, - }, - { - HostPort: 8083, - ContainerPort: 83, - Protocol: v1.ProtocolSCTP, - }, - }, - }, - expectError: false, - }, - { - mapping: &PodPortMapping{ - Name: "pod2", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("2001:beef::3"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8082, - ContainerPort: 80, - Protocol: v1.ProtocolTCP, - }, - { - HostPort: 8081, - ContainerPort: 81, - Protocol: v1.ProtocolUDP, - }, - { - HostPort: 8083, - ContainerPort: 83, - Protocol: v1.ProtocolSCTP, - }, - }, - }, - expectError: true, - }, - { - mapping: &PodPortMapping{ - Name: "pod3", - Namespace: "ns1", - IP: netutils.ParseIPSloppy("2001:beef::4"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8443, - ContainerPort: 443, - Protocol: v1.ProtocolTCP, - }, - }, - }, - expectError: false, - }, - { - mapping: &PodPortMapping{ - Name: "pod4", - Namespace: "ns2", - IP: netutils.ParseIPSloppy("192.168.2.2"), - HostNetwork: false, - PortMappings: []*PortMapping{ - { - HostPort: 8443, - ContainerPort: 443, - Protocol: v1.ProtocolTCP, - }, - }, - }, - expectError: true, - }, - } - - // Add Hostports - for _, tc := range testCases { - err := manager.Add("id", tc.mapping, "cbr0") - if tc.expectError { - assert.Error(t, err) - continue - } - assert.NoError(t, err) - } - - // Check port opened - expectedPorts := []hostport{{IPv6, "", 8080, "tcp"}, {IPv6, "", 8081, "udp"}, {IPv6, "", 8443, "tcp"}} - openedPorts := make(map[hostport]bool) - for hp, port := range portOpener.mem { - if !port.closed { - openedPorts[hp] = true - } - } - assert.EqualValues(t, len(openedPorts), len(expectedPorts)) - for _, hp := range expectedPorts { - _, ok := openedPorts[hp] - assert.EqualValues(t, true, ok) - } - - // Check Iptables-save result after adding hostports - raw := bytes.NewBuffer(nil) - err := iptables.SaveInto(utiliptables.TableNAT, raw) - assert.NoError(t, err) - - lines := strings.Split(raw.String(), "\n") - expectedLines := map[string]bool{ - `*nat`: true, - `:KUBE-HOSTPORTS - [0:0]`: true, - `:OUTPUT - [0:0]`: true, - `:PREROUTING - [0:0]`: true, - `:POSTROUTING - [0:0]`: true, - `:KUBE-HP-IJHALPHTORMHHPPK - [0:0]`: true, - `:KUBE-HP-63UPIDJXVRSZGSUZ - [0:0]`: true, - `:KUBE-HP-WFBOALXEP42XEMJK - [0:0]`: true, - `:KUBE-HP-XU6AWMMJYOZOFTFZ - [0:0]`: true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp --dport 8443 -j KUBE-HP-WFBOALXEP42XEMJK": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8081\" -m udp -p udp --dport 8081 -j KUBE-HP-63UPIDJXVRSZGSUZ": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8080\" -m tcp -p tcp --dport 8080 -j KUBE-HP-IJHALPHTORMHHPPK": true, - "-A KUBE-HOSTPORTS -m comment --comment \"pod1_ns1 hostport 8083\" -m sctp -p sctp --dport 8083 -j KUBE-HP-XU6AWMMJYOZOFTFZ": true, - "-A OUTPUT -m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS": true, - "-A PREROUTING -m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS": true, - "-A POSTROUTING -m comment --comment \"SNAT for localhost access to hostports\" -o cbr0 -s ::1/128 -j MASQUERADE": true, - "-A KUBE-HP-IJHALPHTORMHHPPK -m comment --comment \"pod1_ns1 hostport 8080\" -s 2001:beef::2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-IJHALPHTORMHHPPK -m comment --comment \"pod1_ns1 hostport 8080\" -m tcp -p tcp -j DNAT --to-destination [2001:beef::2]:80": true, - "-A KUBE-HP-63UPIDJXVRSZGSUZ -m comment --comment \"pod1_ns1 hostport 8081\" -s 2001:beef::2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-63UPIDJXVRSZGSUZ -m comment --comment \"pod1_ns1 hostport 8081\" -m udp -p udp -j DNAT --to-destination [2001:beef::2]:81": true, - "-A KUBE-HP-XU6AWMMJYOZOFTFZ -m comment --comment \"pod1_ns1 hostport 8083\" -s 2001:beef::2/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-XU6AWMMJYOZOFTFZ -m comment --comment \"pod1_ns1 hostport 8083\" -m sctp -p sctp -j DNAT --to-destination [2001:beef::2]:83": true, - "-A KUBE-HP-WFBOALXEP42XEMJK -m comment --comment \"pod3_ns1 hostport 8443\" -s 2001:beef::4/32 -j KUBE-MARK-MASQ": true, - "-A KUBE-HP-WFBOALXEP42XEMJK -m comment --comment \"pod3_ns1 hostport 8443\" -m tcp -p tcp -j DNAT --to-destination [2001:beef::4]:443": true, - `COMMIT`: true, - } - for _, line := range lines { - if len(strings.TrimSpace(line)) > 0 { - _, ok := expectedLines[strings.TrimSpace(line)] - assert.EqualValues(t, true, ok) - } - } - - // Remove all added hostports - for _, tc := range testCases { - if !tc.expectError { - err := manager.Remove("id", tc.mapping) - assert.NoError(t, err) - } - } - - // Check Iptables-save result after deleting hostports - raw.Reset() - err = iptables.SaveInto(utiliptables.TableNAT, raw) - assert.NoError(t, err) - lines = strings.Split(raw.String(), "\n") - remainingChains := make(map[string]bool) - for _, line := range lines { - if strings.HasPrefix(line, ":") { - remainingChains[strings.TrimSpace(line)] = true - } - } - expectDeletedChains := []string{"KUBE-HP-4YVONL46AKYWSKS3", "KUBE-HP-7THKRFSEH4GIIXK7", "KUBE-HP-5N7UH5JAXCVP5UJR"} - for _, chain := range expectDeletedChains { - _, ok := remainingChains[chain] - assert.EqualValues(t, false, ok) - } - - // check if all ports are closed - for _, port := range portOpener.mem { - assert.EqualValues(t, true, port.closed) - } -} diff --git a/pkg/kubelet/dockershim/network/hostport/hostport_test.go b/pkg/kubelet/dockershim/network/hostport/hostport_test.go deleted file mode 100644 index 575a0b2bcd9..00000000000 --- a/pkg/kubelet/dockershim/network/hostport/hostport_test.go +++ /dev/null @@ -1,90 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hostport - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" -) - -type fakeSocket struct { - closed bool - port int32 - protocol string - ip string -} - -func (f *fakeSocket) Close() error { - if f.closed { - return fmt.Errorf("socket %q.%s already closed", f.port, f.protocol) - } - f.closed = true - return nil -} - -func NewFakeSocketManager() *fakeSocketManager { - return &fakeSocketManager{mem: make(map[hostport]*fakeSocket)} -} - -type fakeSocketManager struct { - mem map[hostport]*fakeSocket -} - -func (f *fakeSocketManager) openFakeSocket(hp *hostport) (closeable, error) { - if socket, ok := f.mem[*hp]; ok && !socket.closed { - return nil, fmt.Errorf("hostport is occupied") - } - fs := &fakeSocket{ - port: hp.port, - protocol: hp.protocol, - closed: false, - ip: hp.ip, - } - f.mem[*hp] = fs - return fs, nil -} - -func TestEnsureKubeHostportChains(t *testing.T) { - interfaceName := "cbr0" - builtinChains := []string{"PREROUTING", "OUTPUT"} - jumpRule := "-m comment --comment \"kube hostport portals\" -m addrtype --dst-type LOCAL -j KUBE-HOSTPORTS" - masqRule := "-m comment --comment \"SNAT for localhost access to hostports\" -o cbr0 -s 127.0.0.0/8 -j MASQUERADE" - - fakeIPTables := NewFakeIPTables() - assert.NoError(t, ensureKubeHostportChains(fakeIPTables, interfaceName)) - - _, _, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.Chain("KUBE-HOSTPORTS")) - assert.NoError(t, err) - - _, chain, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.ChainPostrouting) - assert.NoError(t, err) - assert.EqualValues(t, len(chain.rules), 1) - assert.Contains(t, chain.rules[0], masqRule) - - for _, chainName := range builtinChains { - _, chain, err := fakeIPTables.getChain(utiliptables.TableNAT, utiliptables.Chain(chainName)) - assert.NoError(t, err) - assert.EqualValues(t, len(chain.rules), 1) - assert.Contains(t, chain.rules[0], jumpRule) - } -} diff --git a/pkg/kubelet/dockershim/network/kubenet/kubenet.go b/pkg/kubelet/dockershim/network/kubenet/kubenet.go deleted file mode 100644 index 159e7f75aee..00000000000 --- a/pkg/kubelet/dockershim/network/kubenet/kubenet.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package kubenet - -const ( - KubenetPluginName = "kubenet" -) diff --git a/pkg/kubelet/dockershim/network/kubenet/kubenet_linux.go b/pkg/kubelet/dockershim/network/kubenet/kubenet_linux.go deleted file mode 100644 index d069336011a..00000000000 --- a/pkg/kubelet/dockershim/network/kubenet/kubenet_linux.go +++ /dev/null @@ -1,930 +0,0 @@ -//go:build linux && !dockerless -// +build linux,!dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package kubenet - -import ( - "context" - "fmt" - "io/ioutil" - "net" - "strings" - "sync" - "time" - - "github.com/containernetworking/cni/libcni" - cnitypes "github.com/containernetworking/cni/pkg/types" - cnitypes020 "github.com/containernetworking/cni/pkg/types/020" - "github.com/vishvananda/netlink" - "golang.org/x/sys/unix" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - utilnet "k8s.io/apimachinery/pkg/util/net" - utilsets "k8s.io/apimachinery/pkg/util/sets" - utilsysctl "k8s.io/component-helpers/node/util/sysctl" - "k8s.io/klog/v2" - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" - "k8s.io/kubernetes/pkg/util/bandwidth" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" - utilexec "k8s.io/utils/exec" - utilebtables "k8s.io/utils/net/ebtables" - - netutils "k8s.io/utils/net" -) - -const ( - BridgeName = "cbr0" - DefaultCNIDir = "/opt/cni/bin" - - sysctlBridgeCallIPTables = "net/bridge/bridge-nf-call-iptables" - - // fallbackMTU is used if an MTU is not specified, and we cannot determine the MTU - fallbackMTU = 1460 - - // ebtables Chain to store dedup rules - dedupChain = utilebtables.Chain("KUBE-DEDUP") - - zeroCIDRv6 = "::/0" - zeroCIDRv4 = "0.0.0.0/0" - - NET_CONFIG_TEMPLATE = `{ - "cniVersion": "0.1.0", - "name": "kubenet", - "type": "bridge", - "bridge": "%s", - "mtu": %d, - "addIf": "%s", - "isGateway": true, - "ipMasq": false, - "hairpinMode": %t, - "ipam": { - "type": "host-local", - "ranges": [%s], - "routes": [%s] - } -}` -) - -// CNI plugins required by kubenet in /opt/cni/bin or user-specified directory -var requiredCNIPlugins = [...]string{"bridge", "host-local", "loopback"} - -type kubenetNetworkPlugin struct { - network.NoopNetworkPlugin - - host network.Host - netConfig *libcni.NetworkConfig - loConfig *libcni.NetworkConfig - cniConfig libcni.CNI - bandwidthShaper bandwidth.Shaper - mu sync.Mutex //Mutex for protecting podIPs map, netConfig, and shaper initialization - podIPs map[kubecontainer.ContainerID]utilsets.String - mtu int - execer utilexec.Interface - nsenterPath string - hairpinMode kubeletconfig.HairpinMode - hostportManager hostport.HostPortManager - hostportManagerv6 hostport.HostPortManager - iptables utiliptables.Interface - iptablesv6 utiliptables.Interface - sysctl utilsysctl.Interface - ebtables utilebtables.Interface - // binDirs is passed by kubelet cni-bin-dir parameter. - // kubenet will search for CNI binaries in DefaultCNIDir first, then continue to binDirs. - binDirs []string - nonMasqueradeCIDR string - cacheDir string - podCIDRs []*net.IPNet -} - -func NewPlugin(networkPluginDirs []string, cacheDir string) network.NetworkPlugin { - execer := utilexec.New() - iptInterface := utiliptables.New(execer, utiliptables.ProtocolIPv4) - iptInterfacev6 := utiliptables.New(execer, utiliptables.ProtocolIPv6) - return &kubenetNetworkPlugin{ - podIPs: make(map[kubecontainer.ContainerID]utilsets.String), - execer: utilexec.New(), - iptables: iptInterface, - iptablesv6: iptInterfacev6, - sysctl: utilsysctl.New(), - binDirs: append([]string{DefaultCNIDir}, networkPluginDirs...), - hostportManager: hostport.NewHostportManager(iptInterface), - hostportManagerv6: hostport.NewHostportManager(iptInterfacev6), - nonMasqueradeCIDR: "10.0.0.0/8", - cacheDir: cacheDir, - podCIDRs: make([]*net.IPNet, 0), - } -} - -func (plugin *kubenetNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { - plugin.host = host - plugin.hairpinMode = hairpinMode - plugin.nonMasqueradeCIDR = nonMasqueradeCIDR - plugin.cniConfig = &libcni.CNIConfig{Path: plugin.binDirs} - - if mtu == network.UseDefaultMTU { - if link, err := findMinMTU(); err == nil { - plugin.mtu = link.MTU - klog.V(5).InfoS("Using the interface MTU value as bridge MTU", "interfaceName", link.Name, "mtuValue", link.MTU) - } else { - plugin.mtu = fallbackMTU - klog.InfoS("Failed to find default bridge MTU, using default value", "mtuValue", fallbackMTU, "err", err) - } - } else { - plugin.mtu = mtu - } - - // Since this plugin uses a Linux bridge, set bridge-nf-call-iptables=1 - // is necessary to ensure kube-proxy functions correctly. - // - // This will return an error on older kernel version (< 3.18) as the module - // was built-in, we simply ignore the error here. A better thing to do is - // to check the kernel version in the future. - plugin.execer.Command("modprobe", "br-netfilter").CombinedOutput() - err := plugin.sysctl.SetSysctl(sysctlBridgeCallIPTables, 1) - if err != nil { - klog.InfoS("can't set sysctl bridge-nf-call-iptables", "err", err) - } - - plugin.loConfig, err = libcni.ConfFromBytes([]byte(`{ - "cniVersion": "0.1.0", - "name": "kubenet-loopback", - "type": "loopback" -}`)) - if err != nil { - return fmt.Errorf("failed to generate loopback config: %v", err) - } - - plugin.nsenterPath, err = plugin.execer.LookPath("nsenter") - if err != nil { - return fmt.Errorf("failed to find nsenter binary: %v", err) - } - - // Need to SNAT outbound traffic from cluster - if err = plugin.ensureMasqRule(); err != nil { - return err - } - return nil -} - -// TODO: move thic logic into cni bridge plugin and remove this from kubenet -func (plugin *kubenetNetworkPlugin) ensureMasqRule() error { - if plugin.nonMasqueradeCIDR != zeroCIDRv4 && plugin.nonMasqueradeCIDR != zeroCIDRv6 { - // switch according to target nonMasqueradeCidr ip family - ipt := plugin.iptables - if netutils.IsIPv6CIDRString(plugin.nonMasqueradeCIDR) { - ipt = plugin.iptablesv6 - } - - if _, err := ipt.EnsureRule(utiliptables.Append, utiliptables.TableNAT, utiliptables.ChainPostrouting, - "-m", "comment", "--comment", "kubenet: SNAT for outbound traffic from cluster", - "-m", "addrtype", "!", "--dst-type", "LOCAL", - "!", "-d", plugin.nonMasqueradeCIDR, - "-j", "MASQUERADE"); err != nil { - return fmt.Errorf("failed to ensure that %s chain %s jumps to MASQUERADE: %v", utiliptables.TableNAT, utiliptables.ChainPostrouting, err) - } - } - return nil -} - -func findMinMTU() (*net.Interface, error) { - intfs, err := net.Interfaces() - if err != nil { - return nil, err - } - - mtu := 999999 - defIntfIndex := -1 - for i, intf := range intfs { - if ((intf.Flags & net.FlagUp) != 0) && (intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) == 0) { - if intf.MTU < mtu { - mtu = intf.MTU - defIntfIndex = i - } - } - } - - if mtu >= 999999 || mtu < 576 || defIntfIndex < 0 { - return nil, fmt.Errorf("no suitable interface: %v", BridgeName) - } - - return &intfs[defIntfIndex], nil -} - -func (plugin *kubenetNetworkPlugin) Event(name string, details map[string]interface{}) { - var err error - if name != network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE { - return - } - - plugin.mu.Lock() - defer plugin.mu.Unlock() - - podCIDR, ok := details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR].(string) - if !ok { - klog.InfoS("The event didn't contain pod CIDR", "event", network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE) - return - } - - if plugin.netConfig != nil { - klog.InfoS("Ignoring subsequent pod CIDR update to new cidr", "podCIDR", podCIDR) - return - } - - klog.V(4).InfoS("Kubenet: PodCIDR is set to new value", "podCIDR", podCIDR) - podCIDRs := strings.Split(podCIDR, ",") - - for idx, currentPodCIDR := range podCIDRs { - _, cidr, err := netutils.ParseCIDRSloppy(currentPodCIDR) - if nil != err { - klog.InfoS("Failed to generate CNI network config with cidr at the index", "podCIDR", currentPodCIDR, "index", idx, "err", err) - return - } - // create list of ips - plugin.podCIDRs = append(plugin.podCIDRs, cidr) - } - - //setup hairpinMode - setHairpin := plugin.hairpinMode == kubeletconfig.HairpinVeth - - json := fmt.Sprintf(NET_CONFIG_TEMPLATE, BridgeName, plugin.mtu, network.DefaultInterfaceName, setHairpin, plugin.getRangesConfig(), plugin.getRoutesConfig()) - klog.V(4).InfoS("CNI network config set to json format", "cniNetworkConfig", json) - plugin.netConfig, err = libcni.ConfFromBytes([]byte(json)) - if err != nil { - klog.InfoS("** failed to set up CNI with json format", "cniNetworkConfig", json, "err", err) - // just incase it was set by mistake - plugin.netConfig = nil - // we bail out by clearing the *entire* list - // of addresses assigned to cbr0 - plugin.clearUnusedBridgeAddresses() - } -} - -// clear all address on bridge except those operated on by kubenet -func (plugin *kubenetNetworkPlugin) clearUnusedBridgeAddresses() { - cidrIncluded := func(list []*net.IPNet, check *net.IPNet) bool { - for _, thisNet := range list { - if utilnet.IPNetEqual(thisNet, check) { - return true - } - } - return false - } - - bridge, err := netlink.LinkByName(BridgeName) - if err != nil { - return - } - - addrs, err := netlink.AddrList(bridge, unix.AF_INET) - if err != nil { - klog.V(2).InfoS("Attempting to get address for the interface failed", "interfaceName", BridgeName, "err", err) - return - } - - for _, addr := range addrs { - if !cidrIncluded(plugin.podCIDRs, addr.IPNet) { - klog.V(2).InfoS("Removing old address from the interface", "interfaceName", BridgeName, "address", addr.IPNet.String()) - netlink.AddrDel(bridge, &addr) - } - } -} - -func (plugin *kubenetNetworkPlugin) Name() string { - return KubenetPluginName -} - -func (plugin *kubenetNetworkPlugin) Capabilities() utilsets.Int { - return utilsets.NewInt() -} - -// setup sets up networking through CNI using the given ns/name and sandbox ID. -func (plugin *kubenetNetworkPlugin) setup(namespace string, name string, id kubecontainer.ContainerID, annotations map[string]string) error { - var ipv4, ipv6 net.IP - var podGateways []net.IP - var podCIDRs []net.IPNet - - // Disable DAD so we skip the kernel delay on bringing up new interfaces. - if err := plugin.disableContainerDAD(id); err != nil { - klog.V(3).InfoS("Failed to disable DAD in container", "err", err) - } - - // Bring up container loopback interface - if _, err := plugin.addContainerToNetwork(plugin.loConfig, "lo", namespace, name, id); err != nil { - return err - } - - // Hook container up with our bridge - resT, err := plugin.addContainerToNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id) - if err != nil { - return err - } - // Coerce the CNI result version - res, err := cnitypes020.GetResult(resT) - if err != nil { - return fmt.Errorf("unable to understand network config: %v", err) - } - //TODO: v1.16 (khenidak) update NET_CONFIG_TEMPLATE to CNI version 0.3.0 or later so - // that we get multiple IP addresses in the returned Result structure - if res.IP4 != nil { - ipv4 = res.IP4.IP.IP.To4() - podGateways = append(podGateways, res.IP4.Gateway) - podCIDRs = append(podCIDRs, net.IPNet{IP: ipv4.Mask(res.IP4.IP.Mask), Mask: res.IP4.IP.Mask}) - } - - if res.IP6 != nil { - ipv6 = res.IP6.IP.IP - podGateways = append(podGateways, res.IP6.Gateway) - podCIDRs = append(podCIDRs, net.IPNet{IP: ipv6.Mask(res.IP6.IP.Mask), Mask: res.IP6.IP.Mask}) - } - - if ipv4 == nil && ipv6 == nil { - return fmt.Errorf("cni didn't report ipv4 ipv6") - } - // Put the container bridge into promiscuous mode to force it to accept hairpin packets. - // TODO: Remove this once the kernel bug (#20096) is fixed. - if plugin.hairpinMode == kubeletconfig.PromiscuousBridge { - link, err := netlink.LinkByName(BridgeName) - if err != nil { - return fmt.Errorf("failed to lookup %q: %v", BridgeName, err) - } - if link.Attrs().Promisc != 1 { - // promiscuous mode is not on, then turn it on. - err := netlink.SetPromiscOn(link) - if err != nil { - return fmt.Errorf("error setting promiscuous mode on %s: %v", BridgeName, err) - } - } - - // configure the ebtables rules to eliminate duplicate packets by best effort - plugin.syncEbtablesDedupRules(link.Attrs().HardwareAddr, podCIDRs, podGateways) - } - - // add the ip to tracked ips - if ipv4 != nil { - plugin.addPodIP(id, ipv4.String()) - } - if ipv6 != nil { - plugin.addPodIP(id, ipv6.String()) - } - - if err := plugin.addTrafficShaping(id, annotations); err != nil { - return err - } - - return plugin.addPortMapping(id, name, namespace) -} - -// The first SetUpPod call creates the bridge; get a shaper for the sake of initialization -// TODO: replace with CNI traffic shaper plugin -func (plugin *kubenetNetworkPlugin) addTrafficShaping(id kubecontainer.ContainerID, annotations map[string]string) error { - shaper := plugin.shaper() - ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations) - if err != nil { - return fmt.Errorf("error reading pod bandwidth annotations: %v", err) - } - iplist, exists := plugin.getCachedPodIPs(id) - if !exists { - return fmt.Errorf("pod %s does not have recorded ips", id) - } - - if egress != nil || ingress != nil { - for _, ip := range iplist { - mask := 32 - if netutils.IsIPv6String(ip) { - mask = 128 - } - if err != nil { - return fmt.Errorf("failed to setup traffic shaping for pod ip%s", ip) - } - - if err := shaper.ReconcileCIDR(fmt.Sprintf("%v/%v", ip, mask), egress, ingress); err != nil { - return fmt.Errorf("failed to add pod to shaper: %v", err) - } - } - } - return nil -} - -// TODO: replace with CNI port-forwarding plugin -func (plugin *kubenetNetworkPlugin) addPortMapping(id kubecontainer.ContainerID, name, namespace string) error { - portMappings, err := plugin.host.GetPodPortMappings(id.ID) - if err != nil { - return err - } - - if len(portMappings) == 0 { - return nil - } - - iplist, exists := plugin.getCachedPodIPs(id) - if !exists { - return fmt.Errorf("pod %s does not have recorded ips", id) - } - - for _, ip := range iplist { - pm := &hostport.PodPortMapping{ - Namespace: namespace, - Name: name, - PortMappings: portMappings, - IP: netutils.ParseIPSloppy(ip), - HostNetwork: false, - } - if netutils.IsIPv6(pm.IP) { - if err := plugin.hostportManagerv6.Add(id.ID, pm, BridgeName); err != nil { - return err - } - } else { - if err := plugin.hostportManager.Add(id.ID, pm, BridgeName); err != nil { - return err - } - } - } - - return nil -} - -func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations, options map[string]string) error { - start := time.Now() - - if err := plugin.Status(); err != nil { - return fmt.Errorf("kubenet cannot SetUpPod: %v", err) - } - - defer func() { - klog.V(4).InfoS("SetUpPod took time", "pod", klog.KRef(namespace, name), "duration", time.Since(start)) - }() - - if err := plugin.setup(namespace, name, id, annotations); err != nil { - if err := plugin.teardown(namespace, name, id); err != nil { - // Not a hard error or warning - klog.V(4).InfoS("Failed to clean up pod after SetUpPod failure", "pod", klog.KRef(namespace, name), "err", err) - } - return err - } - - // Need to SNAT outbound traffic from cluster - if err := plugin.ensureMasqRule(); err != nil { - klog.ErrorS(err, "Failed to ensure MASQ rule") - } - - return nil -} - -// Tears down as much of a pod's network as it can even if errors occur. Returns -// an aggregate error composed of all errors encountered during the teardown. -func (plugin *kubenetNetworkPlugin) teardown(namespace string, name string, id kubecontainer.ContainerID) error { - errList := []error{} - - // Loopback network deletion failure should not be fatal on teardown - if err := plugin.delContainerFromNetwork(plugin.loConfig, "lo", namespace, name, id); err != nil { - klog.InfoS("Failed to delete loopback network", "err", err) - errList = append(errList, err) - - } - - // no ip dependent actions - if err := plugin.delContainerFromNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id); err != nil { - klog.InfoS("Failed to delete the interface network", "interfaceName", network.DefaultInterfaceName, "err", err) - errList = append(errList, err) - } - - // If there are no IPs registered we can't teardown pod's IP dependencies - iplist, exists := plugin.getCachedPodIPs(id) - if !exists || len(iplist) == 0 { - klog.V(5).InfoS("Container does not have IP registered. Ignoring teardown call", "containerID", id, "pod", klog.KRef(namespace, name)) - return nil - } - - // get the list of port mappings - portMappings, err := plugin.host.GetPodPortMappings(id.ID) - if err != nil { - errList = append(errList, err) - } - - // process each pod IP - for _, ip := range iplist { - isV6 := netutils.IsIPv6String(ip) - klog.V(5).InfoS("Removing pod port mappings from the IP", "IP", ip) - if portMappings != nil && len(portMappings) > 0 { - if isV6 { - if err = plugin.hostportManagerv6.Remove(id.ID, &hostport.PodPortMapping{ - Namespace: namespace, - Name: name, - PortMappings: portMappings, - HostNetwork: false, - }); err != nil { - errList = append(errList, err) - } - } else { - if err = plugin.hostportManager.Remove(id.ID, &hostport.PodPortMapping{ - Namespace: namespace, - Name: name, - PortMappings: portMappings, - HostNetwork: false, - }); err != nil { - errList = append(errList, err) - } - } - } - - klog.V(5).InfoS("Removing pod IP from shaper for the pod", "pod", klog.KRef(namespace, name), "IP", ip) - // shaper uses a cidr, but we are using a single IP. - mask := "32" - if isV6 { - mask = "128" - } - - if err := plugin.shaper().Reset(fmt.Sprintf("%s/%s", ip, mask)); err != nil { - // Possible bandwidth shaping wasn't enabled for this pod anyways - klog.V(4).InfoS("Failed to remove pod IP from shaper", "IP", ip, "err", err) - } - - plugin.removePodIP(id, ip) - } - return utilerrors.NewAggregate(errList) -} - -func (plugin *kubenetNetworkPlugin) TearDownPod(namespace string, name string, id kubecontainer.ContainerID) error { - start := time.Now() - defer func() { - klog.V(4).InfoS("TearDownPod took time", "pod", klog.KRef(namespace, name), "duration", time.Since(start)) - }() - - if plugin.netConfig == nil { - return fmt.Errorf("kubenet needs a PodCIDR to tear down pods") - } - - if err := plugin.teardown(namespace, name, id); err != nil { - return err - } - - // Need to SNAT outbound traffic from cluster - if err := plugin.ensureMasqRule(); err != nil { - klog.ErrorS(err, "Failed to ensure MASQ rule") - } - return nil -} - -// TODO: Use the addToNetwork function to obtain the IP of the Pod. That will assume idempotent ADD call to the plugin. -// Also fix the runtime's call to Status function to be done only in the case that the IP is lost, no need to do periodic calls -func (plugin *kubenetNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*network.PodNetworkStatus, error) { - // try cached version - networkStatus := plugin.getNetworkStatus(id) - if networkStatus != nil { - return networkStatus, nil - } - - // not a cached version, get via network ns - netnsPath, err := plugin.host.GetNetNS(id.ID) - if err != nil { - return nil, fmt.Errorf("kubenet failed to retrieve network namespace path: %v", err) - } - if netnsPath == "" { - return nil, fmt.Errorf("cannot find the network namespace, skipping pod network status for container %q", id) - } - ips, err := network.GetPodIPs(plugin.execer, plugin.nsenterPath, netnsPath, network.DefaultInterfaceName) - if err != nil { - return nil, err - } - - // cache the ips - for _, ip := range ips { - plugin.addPodIP(id, ip.String()) - } - - // return from cached - return plugin.getNetworkStatus(id), nil -} - -// returns networkstatus -func (plugin *kubenetNetworkPlugin) getNetworkStatus(id kubecontainer.ContainerID) *network.PodNetworkStatus { - // Assuming the ip of pod does not change. Try to retrieve ip from kubenet map first. - iplist, ok := plugin.getCachedPodIPs(id) - if !ok { - return nil - } - - if len(iplist) == 0 { - return nil - } - - ips := make([]net.IP, 0, len(iplist)) - for _, ip := range iplist { - ips = append(ips, netutils.ParseIPSloppy(ip)) - } - - return &network.PodNetworkStatus{ - IP: ips[0], - IPs: ips, - } -} - -func (plugin *kubenetNetworkPlugin) Status() error { - // Can't set up pods if we don't have a PodCIDR yet - if plugin.netConfig == nil { - return fmt.Errorf("kubenet does not have netConfig. This is most likely due to lack of PodCIDR") - } - - if !plugin.checkRequiredCNIPlugins() { - return fmt.Errorf("could not locate kubenet required CNI plugins %v at %q", requiredCNIPlugins, plugin.binDirs) - } - return nil -} - -// checkRequiredCNIPlugins returns if all kubenet required cni plugins can be found at /opt/cni/bin or user specified NetworkPluginDir. -func (plugin *kubenetNetworkPlugin) checkRequiredCNIPlugins() bool { - for _, dir := range plugin.binDirs { - if plugin.checkRequiredCNIPluginsInOneDir(dir) { - return true - } - } - return false -} - -// checkRequiredCNIPluginsInOneDir returns true if all required cni plugins are placed in dir -func (plugin *kubenetNetworkPlugin) checkRequiredCNIPluginsInOneDir(dir string) bool { - files, err := ioutil.ReadDir(dir) - if err != nil { - return false - } - for _, cniPlugin := range requiredCNIPlugins { - found := false - for _, file := range files { - if strings.TrimSpace(file.Name()) == cniPlugin { - found = true - break - } - } - if !found { - return false - } - } - return true -} - -func (plugin *kubenetNetworkPlugin) buildCNIRuntimeConf(ifName string, id kubecontainer.ContainerID, needNetNs bool) (*libcni.RuntimeConf, error) { - netnsPath, err := plugin.host.GetNetNS(id.ID) - if needNetNs && err != nil { - klog.ErrorS(err, "Kubenet failed to retrieve network namespace path") - } - - return &libcni.RuntimeConf{ - ContainerID: id.ID, - NetNS: netnsPath, - IfName: ifName, - CacheDir: plugin.cacheDir, - }, nil -} - -func (plugin *kubenetNetworkPlugin) addContainerToNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) (cnitypes.Result, error) { - rt, err := plugin.buildCNIRuntimeConf(ifName, id, true) - if err != nil { - return nil, fmt.Errorf("error building CNI config: %v", err) - } - - klog.V(3).InfoS("Adding pod to network with CNI plugin and runtime", "pod", klog.KRef(namespace, name), "networkName", config.Network.Name, "networkType", config.Network.Type, "rt", rt) - // Because the default remote runtime request timeout is 4 min,so set slightly less than 240 seconds - // Todo get the timeout from parent ctx - cniTimeoutCtx, cancelFunc := context.WithTimeout(context.Background(), network.CNITimeoutSec*time.Second) - defer cancelFunc() - res, err := plugin.cniConfig.AddNetwork(cniTimeoutCtx, config, rt) - if err != nil { - return nil, fmt.Errorf("error adding container to network: %v", err) - } - return res, nil -} - -func (plugin *kubenetNetworkPlugin) delContainerFromNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) error { - rt, err := plugin.buildCNIRuntimeConf(ifName, id, false) - if err != nil { - return fmt.Errorf("error building CNI config: %v", err) - } - - klog.V(3).InfoS("Removing pod from network with CNI plugin and runtime", "pod", klog.KRef(namespace, name), "networkName", config.Network.Name, "networkType", config.Network.Type, "rt", rt) - // Because the default remote runtime request timeout is 4 min,so set slightly less than 240 seconds - // Todo get the timeout from parent ctx - cniTimeoutCtx, cancelFunc := context.WithTimeout(context.Background(), network.CNITimeoutSec*time.Second) - defer cancelFunc() - err = plugin.cniConfig.DelNetwork(cniTimeoutCtx, config, rt) - // The pod may not get deleted successfully at the first time. - // Ignore "no such file or directory" error in case the network has already been deleted in previous attempts. - if err != nil && !strings.Contains(err.Error(), "no such file or directory") { - return fmt.Errorf("error removing container from network: %v", err) - } - return nil -} - -// shaper retrieves the bandwidth shaper and, if it hasn't been fetched before, -// initializes it and ensures the bridge is appropriately configured -func (plugin *kubenetNetworkPlugin) shaper() bandwidth.Shaper { - plugin.mu.Lock() - defer plugin.mu.Unlock() - if plugin.bandwidthShaper == nil { - plugin.bandwidthShaper = bandwidth.NewTCShaper(BridgeName) - plugin.bandwidthShaper.ReconcileInterface() - } - return plugin.bandwidthShaper -} - -//TODO: make this into a goroutine and rectify the dedup rules periodically -func (plugin *kubenetNetworkPlugin) syncEbtablesDedupRules(macAddr net.HardwareAddr, podCIDRs []net.IPNet, podGateways []net.IP) { - if plugin.ebtables == nil { - plugin.ebtables = utilebtables.New(plugin.execer) - klog.V(3).InfoS("Flushing dedup chain") - if err := plugin.ebtables.FlushChain(utilebtables.TableFilter, dedupChain); err != nil { - klog.ErrorS(err, "Failed to flush dedup chain") - } - } - _, err := plugin.ebtables.GetVersion() - if err != nil { - klog.InfoS("Failed to get ebtables version. Skip syncing ebtables dedup rules", "err", err) - return - } - - // ensure custom chain exists - _, err = plugin.ebtables.EnsureChain(utilebtables.TableFilter, dedupChain) - if err != nil { - klog.ErrorS(nil, "Failed to ensure filter table KUBE-DEDUP chain") - return - } - - // jump to custom chain to the chain from core tables - _, err = plugin.ebtables.EnsureRule(utilebtables.Append, utilebtables.TableFilter, utilebtables.ChainOutput, "-j", string(dedupChain)) - if err != nil { - klog.ErrorS(err, "Failed to ensure filter table OUTPUT chain jump to KUBE-DEDUP chain") - return - } - - // per gateway rule - for idx, gw := range podGateways { - klog.V(3).InfoS("Filtering packets with ebtables", "mac", macAddr.String(), "gateway", gw.String(), "podCIDR", podCIDRs[idx].String()) - - bIsV6 := netutils.IsIPv6(gw) - IPFamily := "IPv4" - ipSrc := "--ip-src" - if bIsV6 { - IPFamily = "IPv6" - ipSrc = "--ip6-src" - } - commonArgs := []string{"-p", IPFamily, "-s", macAddr.String(), "-o", "veth+"} - _, err = plugin.ebtables.EnsureRule(utilebtables.Prepend, utilebtables.TableFilter, dedupChain, append(commonArgs, ipSrc, gw.String(), "-j", "ACCEPT")...) - if err != nil { - klog.ErrorS(err, "Failed to ensure packets from cbr0 gateway to be accepted with error", "gateway", gw.String()) - return - - } - _, err = plugin.ebtables.EnsureRule(utilebtables.Append, utilebtables.TableFilter, dedupChain, append(commonArgs, ipSrc, podCIDRs[idx].String(), "-j", "DROP")...) - if err != nil { - klog.ErrorS(err, "Failed to ensure packets from podCidr but has mac address of cbr0 to get dropped.", "podCIDR", podCIDRs[idx].String()) - return - } - } -} - -// disableContainerDAD disables duplicate address detection in the container. -// DAD has a negative affect on pod creation latency, since we have to wait -// a second or more for the addresses to leave the "tentative" state. Since -// we're sure there won't be an address conflict (since we manage them manually), -// this is safe. See issue 54651. -// -// This sets net.ipv6.conf.default.dad_transmits to 0. It must be run *before* -// the CNI plugins are run. -func (plugin *kubenetNetworkPlugin) disableContainerDAD(id kubecontainer.ContainerID) error { - key := "net/ipv6/conf/default/dad_transmits" - - sysctlBin, err := plugin.execer.LookPath("sysctl") - if err != nil { - return fmt.Errorf("could not find sysctl binary: %s", err) - } - - netnsPath, err := plugin.host.GetNetNS(id.ID) - if err != nil { - return fmt.Errorf("failed to get netns: %v", err) - } - if netnsPath == "" { - return fmt.Errorf("pod has no network namespace") - } - - // If the sysctl doesn't exist, it means ipv6 is disabled; log and move on - if _, err := plugin.sysctl.GetSysctl(key); err != nil { - return fmt.Errorf("ipv6 not enabled: %v", err) - } - - output, err := plugin.execer.Command(plugin.nsenterPath, - fmt.Sprintf("--net=%s", netnsPath), "-F", "--", - sysctlBin, "-w", fmt.Sprintf("%s=%s", key, "0"), - ).CombinedOutput() - if err != nil { - return fmt.Errorf("failed to write sysctl: output: %s error: %s", - output, err) - } - return nil -} - -// given a n cidrs assigned to nodes, -// create bridge configuration that conforms to them -func (plugin *kubenetNetworkPlugin) getRangesConfig() string { - createRange := func(thisNet *net.IPNet) string { - template := ` -[{ -"subnet": "%s" -}]` - return fmt.Sprintf(template, thisNet.String()) - } - - ranges := make([]string, len(plugin.podCIDRs)) - for idx, thisCIDR := range plugin.podCIDRs { - ranges[idx] = createRange(thisCIDR) - } - //[{range}], [{range}] - // each range contains a subnet. gateway will be fetched from cni result - return strings.Join(ranges[:], ",") -} - -// given a n cidrs assigned to nodes, -// create bridge routes configuration that conforms to them -func (plugin *kubenetNetworkPlugin) getRoutesConfig() string { - var ( - routes []string - hasV4, hasV6 bool - ) - for _, thisCIDR := range plugin.podCIDRs { - if thisCIDR.IP.To4() != nil { - hasV4 = true - } else { - hasV6 = true - } - } - if hasV4 { - routes = append(routes, fmt.Sprintf(`{"dst": "%s"}`, zeroCIDRv4)) - } - if hasV6 { - routes = append(routes, fmt.Sprintf(`{"dst": "%s"}`, zeroCIDRv6)) - } - return strings.Join(routes, ",") -} - -func (plugin *kubenetNetworkPlugin) addPodIP(id kubecontainer.ContainerID, ip string) { - plugin.mu.Lock() - defer plugin.mu.Unlock() - - _, exist := plugin.podIPs[id] - if !exist { - plugin.podIPs[id] = utilsets.NewString() - } - - if !plugin.podIPs[id].Has(ip) { - plugin.podIPs[id].Insert(ip) - } -} - -func (plugin *kubenetNetworkPlugin) removePodIP(id kubecontainer.ContainerID, ip string) { - plugin.mu.Lock() - defer plugin.mu.Unlock() - - _, exist := plugin.podIPs[id] - if !exist { - return // did we restart kubelet? - } - - if plugin.podIPs[id].Has(ip) { - plugin.podIPs[id].Delete(ip) - } - - // if there is no more ips here. let us delete - if plugin.podIPs[id].Len() == 0 { - delete(plugin.podIPs, id) - } -} - -// returns a copy of pod ips -// false is returned if id does not exist -func (plugin *kubenetNetworkPlugin) getCachedPodIPs(id kubecontainer.ContainerID) ([]string, bool) { - plugin.mu.Lock() - defer plugin.mu.Unlock() - - iplist, exists := plugin.podIPs[id] - if !exists { - return nil, false - } - - return iplist.UnsortedList(), true -} diff --git a/pkg/kubelet/dockershim/network/kubenet/kubenet_linux_test.go b/pkg/kubelet/dockershim/network/kubenet/kubenet_linux_test.go deleted file mode 100644 index e94f93726f5..00000000000 --- a/pkg/kubelet/dockershim/network/kubenet/kubenet_linux_test.go +++ /dev/null @@ -1,392 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package kubenet - -import ( - "fmt" - "net" - "strings" - "testing" - - "github.com/containernetworking/cni/libcni" - "github.com/containernetworking/cni/pkg/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - - utilsets "k8s.io/apimachinery/pkg/util/sets" - sysctltest "k8s.io/component-helpers/node/util/sysctl/testing" - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - mockcni "k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni/testing" - nettest "k8s.io/kubernetes/pkg/kubelet/dockershim/network/testing" - "k8s.io/kubernetes/pkg/util/bandwidth" - ipttest "k8s.io/kubernetes/pkg/util/iptables/testing" - "k8s.io/utils/exec" - fakeexec "k8s.io/utils/exec/testing" - netutils "k8s.io/utils/net" -) - -// test it fulfills the NetworkPlugin interface -var _ network.NetworkPlugin = &kubenetNetworkPlugin{} - -func newFakeKubenetPlugin(initMap map[kubecontainer.ContainerID]utilsets.String, execer exec.Interface, host network.Host) *kubenetNetworkPlugin { - return &kubenetNetworkPlugin{ - podIPs: initMap, - execer: execer, - mtu: 1460, - host: host, - } -} - -func TestGetPodNetworkStatus(t *testing.T) { - podIPMap := make(map[kubecontainer.ContainerID]utilsets.String) - podIPMap[kubecontainer.ContainerID{ID: "1"}] = utilsets.NewString("10.245.0.2") - podIPMap[kubecontainer.ContainerID{ID: "2"}] = utilsets.NewString("10.245.0.3") - podIPMap[kubecontainer.ContainerID{ID: "3"}] = utilsets.NewString("10.245.0.4", "2000::") - podIPMap[kubecontainer.ContainerID{ID: "4"}] = utilsets.NewString("2000::2") - - testCases := []struct { - id string - expectError bool - expectIP utilsets.String - }{ - //in podCIDR map - { - id: "1", - expectError: false, - expectIP: utilsets.NewString("10.245.0.2"), - }, - { - id: "2", - expectError: false, - expectIP: utilsets.NewString("10.245.0.3"), - }, - { - id: "3", - expectError: false, - expectIP: utilsets.NewString("10.245.0.4", "2000::"), - }, - { - id: "4", - expectError: false, - expectIP: utilsets.NewString("2000::2"), - }, - - //not in podIP map - { - id: "does-not-exist-map", - expectError: true, - expectIP: nil, - }, - //TODO: add test cases for retrieving ip inside container network namespace - } - - fakeCmds := make([]fakeexec.FakeCommandAction, 0) - for _, t := range testCases { - // the fake commands return the IP from the given index, or an error - fCmd := fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeAction{ - func() ([]byte, []byte, error) { - ips, ok := podIPMap[kubecontainer.ContainerID{ID: t.id}] - if !ok { - return nil, nil, fmt.Errorf("Pod IP %q not found", t.id) - } - ipsList := ips.UnsortedList() - return []byte(ipsList[0]), nil, nil - }, - }, - } - fakeCmds = append(fakeCmds, func(cmd string, args ...string) exec.Cmd { - return fakeexec.InitFakeCmd(&fCmd, cmd, args...) - }) - } - fexec := fakeexec.FakeExec{ - CommandScript: fakeCmds, - LookPathFunc: func(file string) (string, error) { - return fmt.Sprintf("/fake-bin/%s", file), nil - }, - } - - fhost := nettest.NewFakeHost(nil) - fakeKubenet := newFakeKubenetPlugin(podIPMap, &fexec, fhost) - - for i, tc := range testCases { - out, err := fakeKubenet.GetPodNetworkStatus("", "", kubecontainer.ContainerID{ID: tc.id}) - if tc.expectError { - if err == nil { - t.Errorf("Test case %d expects error but got none", i) - } - continue - } else { - if err != nil { - t.Errorf("Test case %d expects error but got error: %v", i, err) - } - } - seen := make(map[string]bool) - allExpected := tc.expectIP.UnsortedList() - for _, expectedIP := range allExpected { - for _, outIP := range out.IPs { - if expectedIP == outIP.String() { - seen[expectedIP] = true - break - } - } - } - if len(tc.expectIP) != len(seen) { - t.Errorf("Test case %d expects ip %s but got %s", i, tc.expectIP, out.IP.String()) - } - - } -} - -// TestTeardownCallsShaper tests that a `TearDown` call does call -// `shaper.Reset` -func TestTeardownCallsShaper(t *testing.T) { - fexec := &fakeexec.FakeExec{ - CommandScript: []fakeexec.FakeCommandAction{}, - LookPathFunc: func(file string) (string, error) { - return fmt.Sprintf("/fake-bin/%s", file), nil - }, - } - fhost := nettest.NewFakeHost(nil) - fshaper := &bandwidth.FakeShaper{} - mockcni := &mockcni.MockCNI{} - ips := make(map[kubecontainer.ContainerID]utilsets.String) - kubenet := newFakeKubenetPlugin(ips, fexec, fhost) - kubenet.loConfig = &libcni.NetworkConfig{ - Network: &types.NetConf{ - Name: "loopback-fake", - Type: "loopback", - }, - } - kubenet.cniConfig = mockcni - kubenet.iptables = ipttest.NewFake() - kubenet.bandwidthShaper = fshaper - - mockcni.On("DelNetwork", mock.AnythingOfType("*context.timerCtx"), mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil) - - details := make(map[string]interface{}) - details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = "10.0.0.1/24" - kubenet.Event(network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE, details) - - existingContainerID := kubecontainer.BuildContainerID("docker", "123") - kubenet.podIPs[existingContainerID] = utilsets.NewString("10.0.0.1") - - if err := kubenet.TearDownPod("namespace", "name", existingContainerID); err != nil { - t.Fatalf("Unexpected error in TearDownPod: %v", err) - } - assert.Equal(t, []string{"10.0.0.1/32"}, fshaper.ResetCIDRs, "shaper.Reset should have been called") - - mockcni.AssertExpectations(t) -} - -// TestInit tests that a `Init` call with an MTU sets the MTU -func TestInit_MTU(t *testing.T) { - var fakeCmds []fakeexec.FakeCommandAction - { - // modprobe br-netfilter - fCmd := fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeAction{ - func() ([]byte, []byte, error) { - return make([]byte, 0), nil, nil - }, - }, - } - fakeCmds = append(fakeCmds, func(cmd string, args ...string) exec.Cmd { - return fakeexec.InitFakeCmd(&fCmd, cmd, args...) - }) - } - - fexec := &fakeexec.FakeExec{ - CommandScript: fakeCmds, - LookPathFunc: func(file string) (string, error) { - return fmt.Sprintf("/fake-bin/%s", file), nil - }, - } - - fhost := nettest.NewFakeHost(nil) - ips := make(map[kubecontainer.ContainerID]utilsets.String) - kubenet := newFakeKubenetPlugin(ips, fexec, fhost) - kubenet.iptables = ipttest.NewFake() - - sysctl := sysctltest.NewFake() - sysctl.Settings["net/bridge/bridge-nf-call-iptables"] = 0 - kubenet.sysctl = sysctl - - if err := kubenet.Init(nettest.NewFakeHost(nil), kubeletconfig.HairpinNone, "10.0.0.0/8", 1234); err != nil { - t.Fatalf("Unexpected error in Init: %v", err) - } - assert.Equal(t, 1234, kubenet.mtu, "kubenet.mtu should have been set") - assert.Equal(t, 1, sysctl.Settings["net/bridge/bridge-nf-call-iptables"], "net/bridge/bridge-nf-call-iptables sysctl should have been set") -} - -// TestInvocationWithoutRuntime invokes the plugin without a runtime. -// This is how kubenet is invoked from the cri. -func TestTearDownWithoutRuntime(t *testing.T) { - testCases := []struct { - podCIDR []string - expectedPodCIDR []string - ip string - }{ - { - podCIDR: []string{"10.0.0.0/24"}, - expectedPodCIDR: []string{"10.0.0.0/24"}, - ip: "10.0.0.1", - }, - { - podCIDR: []string{"10.0.0.1/24"}, - expectedPodCIDR: []string{"10.0.0.0/24"}, - ip: "10.0.0.1", - }, - { - podCIDR: []string{"2001:beef::/48"}, - expectedPodCIDR: []string{"2001:beef::/48"}, - ip: "2001:beef::1", - }, - { - podCIDR: []string{"2001:beef::1/48"}, - expectedPodCIDR: []string{"2001:beef::/48"}, - ip: "2001:beef::1", - }, - } - for _, tc := range testCases { - - fhost := nettest.NewFakeHost(nil) - fhost.Legacy = false - mockcni := &mockcni.MockCNI{} - - fexec := &fakeexec.FakeExec{ - CommandScript: []fakeexec.FakeCommandAction{}, - LookPathFunc: func(file string) (string, error) { - return fmt.Sprintf("/fake-bin/%s", file), nil - }, - } - - ips := make(map[kubecontainer.ContainerID]utilsets.String) - kubenet := newFakeKubenetPlugin(ips, fexec, fhost) - kubenet.loConfig = &libcni.NetworkConfig{ - Network: &types.NetConf{ - Name: "loopback-fake", - Type: "loopback", - }, - } - kubenet.cniConfig = mockcni - kubenet.iptables = ipttest.NewFake() - - details := make(map[string]interface{}) - details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = strings.Join(tc.podCIDR, ",") - kubenet.Event(network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE, details) - - if len(kubenet.podCIDRs) != len(tc.podCIDR) { - t.Errorf("generated podCidr: %q, expecting: %q are not of the same length", kubenet.podCIDRs, tc.podCIDR) - continue - } - for idx := range tc.podCIDR { - if kubenet.podCIDRs[idx].String() != tc.expectedPodCIDR[idx] { - t.Errorf("generated podCidr: %q, expecting: %q", kubenet.podCIDRs[idx].String(), tc.expectedPodCIDR[idx]) - } - } - - existingContainerID := kubecontainer.BuildContainerID("docker", "123") - kubenet.podIPs[existingContainerID] = utilsets.NewString(tc.ip) - - mockcni.On("DelNetwork", mock.AnythingOfType("*context.timerCtx"), mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil) - - if err := kubenet.TearDownPod("namespace", "name", existingContainerID); err != nil { - t.Fatalf("Unexpected error in TearDownPod: %v", err) - } - // Assert that the CNI DelNetwork made it through and we didn't crash - // without a runtime. - mockcni.AssertExpectations(t) - } -} - -func TestGetRoutesConfig(t *testing.T) { - for _, test := range []struct { - cidrs []string - routes string - }{ - { - cidrs: []string{"10.0.0.1/24"}, - routes: `{"dst": "0.0.0.0/0"}`, - }, - { - cidrs: []string{"2001:4860:4860::8888/32"}, - routes: `{"dst": "::/0"}`, - }, - { - cidrs: []string{"2001:4860:4860::8888/32", "10.0.0.1/24"}, - routes: `{"dst": "0.0.0.0/0"},{"dst": "::/0"}`, - }, - } { - var cidrs []*net.IPNet - for _, c := range test.cidrs { - _, cidr, err := netutils.ParseCIDRSloppy(c) - assert.NoError(t, err) - cidrs = append(cidrs, cidr) - } - fakeKubenet := &kubenetNetworkPlugin{podCIDRs: cidrs} - assert.Equal(t, test.routes, fakeKubenet.getRoutesConfig()) - } -} - -func TestGetRangesConfig(t *testing.T) { - for _, test := range []struct { - cidrs []string - ranges string - }{ - { - cidrs: []string{"10.0.0.0/24"}, - ranges: ` -[{ -"subnet": "10.0.0.0/24" -}]`, - }, - { - cidrs: []string{"2001:4860::/32"}, - ranges: ` -[{ -"subnet": "2001:4860::/32" -}]`, - }, - { - cidrs: []string{"10.0.0.0/24", "2001:4860::/32"}, - ranges: ` -[{ -"subnet": "10.0.0.0/24" -}], -[{ -"subnet": "2001:4860::/32" -}]`, - }, - } { - var cidrs []*net.IPNet - for _, c := range test.cidrs { - _, cidr, err := netutils.ParseCIDRSloppy(c) - assert.NoError(t, err) - cidrs = append(cidrs, cidr) - } - fakeKubenet := &kubenetNetworkPlugin{podCIDRs: cidrs} - assert.Equal(t, test.ranges, fakeKubenet.getRangesConfig()) - } -} - -//TODO: add unit test for each implementation of network plugin interface diff --git a/pkg/kubelet/dockershim/network/kubenet/kubenet_unsupported.go b/pkg/kubelet/dockershim/network/kubenet/kubenet_unsupported.go deleted file mode 100644 index c9adf1c6d3d..00000000000 --- a/pkg/kubelet/dockershim/network/kubenet/kubenet_unsupported.go +++ /dev/null @@ -1,56 +0,0 @@ -//go:build !linux && !dockerless -// +build !linux,!dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package kubenet - -import ( - "fmt" - - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" -) - -type kubenetNetworkPlugin struct { - network.NoopNetworkPlugin -} - -func NewPlugin(networkPluginDirs []string, cacheDir string) network.NetworkPlugin { - return &kubenetNetworkPlugin{} -} - -func (plugin *kubenetNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { - return fmt.Errorf("Kubenet is not supported in this build") -} - -func (plugin *kubenetNetworkPlugin) Name() string { - return "kubenet" -} - -func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations, options map[string]string) error { - return fmt.Errorf("Kubenet is not supported in this build") -} - -func (plugin *kubenetNetworkPlugin) TearDownPod(namespace string, name string, id kubecontainer.ContainerID) error { - return fmt.Errorf("Kubenet is not supported in this build") -} - -func (plugin *kubenetNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*network.PodNetworkStatus, error) { - return nil, fmt.Errorf("Kubenet is not supported in this build") -} diff --git a/pkg/kubelet/dockershim/network/metrics/metrics.go b/pkg/kubelet/dockershim/network/metrics/metrics.go deleted file mode 100644 index 318feabe31a..00000000000 --- a/pkg/kubelet/dockershim/network/metrics/metrics.go +++ /dev/null @@ -1,93 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package metrics - -import ( - "sync" - "time" - - "k8s.io/component-base/metrics" - "k8s.io/component-base/metrics/legacyregistry" -) - -const ( - // NetworkPluginOperationsKey is the key for operation count metrics. - NetworkPluginOperationsKey = "network_plugin_operations_total" - // NetworkPluginOperationsLatencyKey is the key for the operation latency metrics. - NetworkPluginOperationsLatencyKey = "network_plugin_operations_duration_seconds" - // NetworkPluginOperationsErrorsKey is the key for the operations error metrics. - NetworkPluginOperationsErrorsKey = "network_plugin_operations_errors_total" - - // Keep the "kubelet" subsystem for backward compatibility. - kubeletSubsystem = "kubelet" -) - -var ( - // NetworkPluginOperationsLatency collects operation latency numbers by operation - // type. - NetworkPluginOperationsLatency = metrics.NewHistogramVec( - &metrics.HistogramOpts{ - Subsystem: kubeletSubsystem, - Name: NetworkPluginOperationsLatencyKey, - Help: "Latency in seconds of network plugin operations. Broken down by operation type.", - Buckets: metrics.DefBuckets, - StabilityLevel: metrics.ALPHA, - }, - []string{"operation_type"}, - ) - - // NetworkPluginOperations collects operation counts by operation type. - NetworkPluginOperations = metrics.NewCounterVec( - &metrics.CounterOpts{ - Subsystem: kubeletSubsystem, - Name: NetworkPluginOperationsKey, - Help: "Cumulative number of network plugin operations by operation type.", - StabilityLevel: metrics.ALPHA, - }, - []string{"operation_type"}, - ) - - // NetworkPluginOperationsErrors collects operation errors by operation type. - NetworkPluginOperationsErrors = metrics.NewCounterVec( - &metrics.CounterOpts{ - Subsystem: kubeletSubsystem, - Name: NetworkPluginOperationsErrorsKey, - Help: "Cumulative number of network plugin operation errors by operation type.", - StabilityLevel: metrics.ALPHA, - }, - []string{"operation_type"}, - ) -) - -var registerMetrics sync.Once - -// Register all metrics. -func Register() { - registerMetrics.Do(func() { - legacyregistry.MustRegister(NetworkPluginOperationsLatency) - legacyregistry.MustRegister(NetworkPluginOperations) - legacyregistry.MustRegister(NetworkPluginOperationsErrors) - }) -} - -// SinceInSeconds gets the time since the specified start in seconds. -func SinceInSeconds(start time.Time) float64 { - return time.Since(start).Seconds() -} diff --git a/pkg/kubelet/dockershim/network/network.go b/pkg/kubelet/dockershim/network/network.go deleted file mode 100644 index 82869c7aaf5..00000000000 --- a/pkg/kubelet/dockershim/network/network.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package network - -// TODO: Consider making this value configurable. -const DefaultInterfaceName = "eth0" - -// CNITimeoutSec is set to be slightly less than 240sec/4mins, which is the default remote runtime request timeout. -const CNITimeoutSec = 220 - -// UseDefaultMTU is a marker value that indicates the plugin should determine its own MTU -// It is the zero value, so a non-initialized value will mean "UseDefault" -const UseDefaultMTU = 0 diff --git a/pkg/kubelet/dockershim/network/plugins.go b/pkg/kubelet/dockershim/network/plugins.go deleted file mode 100644 index a3eea046677..00000000000 --- a/pkg/kubelet/dockershim/network/plugins.go +++ /dev/null @@ -1,427 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes 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. -*/ - -//go:generate mockgen -copyright_file=$BUILD_TAG_FILE -source=plugins.go -destination=testing/mock_network_plugin.go -package=testing NetworkPlugin -package network - -import ( - "fmt" - "net" - "strings" - "sync" - "time" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - utilsets "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/util/validation" - utilsysctl "k8s.io/component-helpers/node/util/sysctl" - "k8s.io/klog/v2" - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics" - utilexec "k8s.io/utils/exec" - netutils "k8s.io/utils/net" -) - -const ( - DefaultPluginName = "kubernetes.io/no-op" - - // Called when the node's Pod CIDR is known when using the - // controller manager's --allocate-node-cidrs=true option - NET_PLUGIN_EVENT_POD_CIDR_CHANGE = "pod-cidr-change" - NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR = "pod-cidr" -) - -// NetworkPlugin is an interface to network plugins for the kubelet -type NetworkPlugin interface { - // Init initializes the plugin. This will be called exactly once - // before any other methods are called. - Init(host Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error - - // Called on various events like: - // NET_PLUGIN_EVENT_POD_CIDR_CHANGE - Event(name string, details map[string]interface{}) - - // Name returns the plugin's name. This will be used when searching - // for a plugin by name, e.g. - Name() string - - // Returns a set of NET_PLUGIN_CAPABILITY_* - Capabilities() utilsets.Int - - // SetUpPod is the method called after the infra container of - // the pod has been created but before the other containers of the - // pod are launched. - SetUpPod(namespace string, name string, podSandboxID kubecontainer.ContainerID, annotations, options map[string]string) error - - // TearDownPod is the method called before a pod's infra container will be deleted - TearDownPod(namespace string, name string, podSandboxID kubecontainer.ContainerID) error - - // GetPodNetworkStatus is the method called to obtain the ipv4 or ipv6 addresses of the container - GetPodNetworkStatus(namespace string, name string, podSandboxID kubecontainer.ContainerID) (*PodNetworkStatus, error) - - // Status returns error if the network plugin is in error state - Status() error -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// PodNetworkStatus stores the network status of a pod (currently just the primary IP address) -// This struct represents version "v1beta1" -type PodNetworkStatus struct { - metav1.TypeMeta `json:",inline"` - - // IP is the primary ipv4/ipv6 address of the pod. Among other things it is the address that - - // - kube expects to be reachable across the cluster - // - service endpoints are constructed with - // - will be reported in the PodStatus.PodIP field (will override the IP reported by docker) - IP net.IP `json:"ip" description:"Primary IP address of the pod"` - // IPs is the list of IPs assigned to Pod. IPs[0] == IP. The rest of the list is additional IPs - IPs []net.IP `json:"ips" description:"list of additional ips (inclusive of IP) assigned to pod"` -} - -// Host is an interface that plugins can use to access the kubelet. -// TODO(#35457): get rid of this backchannel to the kubelet. The scope of -// the back channel is restricted to host-ports/testing, and restricted -// to kubenet. No other network plugin wrapper needs it. Other plugins -// only require a way to access namespace information and port mapping -// information , which they can do directly through the embedded interfaces. -type Host interface { - // NamespaceGetter is a getter for sandbox namespace information. - NamespaceGetter - - // PortMappingGetter is a getter for sandbox port mapping information. - PortMappingGetter -} - -// NamespaceGetter is an interface to retrieve namespace information for a given -// podSandboxID. Typically implemented by runtime shims that are closely coupled to -// CNI plugin wrappers like kubenet. -type NamespaceGetter interface { - // GetNetNS returns network namespace information for the given containerID. - // Runtimes should *never* return an empty namespace and nil error for - // a container; if error is nil then the namespace string must be valid. - GetNetNS(containerID string) (string, error) -} - -// PortMappingGetter is an interface to retrieve port mapping information for a given -// podSandboxID. Typically implemented by runtime shims that are closely coupled to -// CNI plugin wrappers like kubenet. -type PortMappingGetter interface { - // GetPodPortMappings returns sandbox port mappings information. - GetPodPortMappings(containerID string) ([]*hostport.PortMapping, error) -} - -// InitNetworkPlugin inits the plugin that matches networkPluginName. Plugins must have unique names. -func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) (NetworkPlugin, error) { - if networkPluginName == "" { - // default to the no_op plugin - plug := &NoopNetworkPlugin{} - plug.Sysctl = utilsysctl.New() - if err := plug.Init(host, hairpinMode, nonMasqueradeCIDR, mtu); err != nil { - return nil, err - } - return plug, nil - } - - pluginMap := map[string]NetworkPlugin{} - - allErrs := []error{} - for _, plugin := range plugins { - name := plugin.Name() - if errs := validation.IsQualifiedName(name); len(errs) != 0 { - allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %q: %s", name, strings.Join(errs, ";"))) - continue - } - - if _, found := pluginMap[name]; found { - allErrs = append(allErrs, fmt.Errorf("network plugin %q was registered more than once", name)) - continue - } - pluginMap[name] = plugin - } - - chosenPlugin := pluginMap[networkPluginName] - if chosenPlugin != nil { - err := chosenPlugin.Init(host, hairpinMode, nonMasqueradeCIDR, mtu) - if err != nil { - allErrs = append(allErrs, fmt.Errorf("network plugin %q failed init: %v", networkPluginName, err)) - } else { - klog.V(1).InfoS("Loaded network plugin", "networkPluginName", networkPluginName) - } - } else { - allErrs = append(allErrs, fmt.Errorf("network plugin %q not found", networkPluginName)) - } - - return chosenPlugin, utilerrors.NewAggregate(allErrs) -} - -type NoopNetworkPlugin struct { - Sysctl utilsysctl.Interface -} - -const sysctlBridgeCallIPTables = "net/bridge/bridge-nf-call-iptables" -const sysctlBridgeCallIP6Tables = "net/bridge/bridge-nf-call-ip6tables" - -func (plugin *NoopNetworkPlugin) Init(host Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { - // Set bridge-nf-call-iptables=1 to maintain compatibility with older - // kubernetes versions to ensure the iptables-based kube proxy functions - // correctly. Other plugins are responsible for setting this correctly - // depending on whether or not they connect containers to Linux bridges - // or use some other mechanism (ie, SDN vswitch). - - // Ensure the netfilter module is loaded on kernel >= 3.18; previously - // it was built-in. - utilexec.New().Command("modprobe", "br-netfilter").CombinedOutput() - if err := plugin.Sysctl.SetSysctl(sysctlBridgeCallIPTables, 1); err != nil { - klog.InfoS("can't set sysctl bridge-nf-call-iptables", "err", err) - } - if val, err := plugin.Sysctl.GetSysctl(sysctlBridgeCallIP6Tables); err == nil { - if val != 1 { - if err = plugin.Sysctl.SetSysctl(sysctlBridgeCallIP6Tables, 1); err != nil { - klog.InfoS("can't set sysctl bridge-nf-call-ip6tables", "err", err) - } - } - } - - return nil -} - -func (plugin *NoopNetworkPlugin) Event(name string, details map[string]interface{}) { -} - -func (plugin *NoopNetworkPlugin) Name() string { - return DefaultPluginName -} - -func (plugin *NoopNetworkPlugin) Capabilities() utilsets.Int { - return utilsets.NewInt() -} - -func (plugin *NoopNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations, options map[string]string) error { - return nil -} - -func (plugin *NoopNetworkPlugin) TearDownPod(namespace string, name string, id kubecontainer.ContainerID) error { - return nil -} - -func (plugin *NoopNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*PodNetworkStatus, error) { - return nil, nil -} - -func (plugin *NoopNetworkPlugin) Status() error { - return nil -} - -func getOnePodIP(execer utilexec.Interface, nsenterPath, netnsPath, interfaceName, addrType string) (net.IP, error) { - // Try to retrieve ip inside container network namespace - output, err := execer.Command(nsenterPath, fmt.Sprintf("--net=%s", netnsPath), "-F", "--", - "ip", "-o", addrType, "addr", "show", "dev", interfaceName, "scope", "global").CombinedOutput() - if err != nil { - return nil, fmt.Errorf("unexpected command output %s with error: %v", output, err) - } - - lines := strings.Split(string(output), "\n") - if len(lines) < 1 { - return nil, fmt.Errorf("unexpected command output %s", output) - } - fields := strings.Fields(lines[0]) - if len(fields) < 4 { - return nil, fmt.Errorf("unexpected address output %s ", lines[0]) - } - ip, _, err := netutils.ParseCIDRSloppy(fields[3]) - if err != nil { - return nil, fmt.Errorf("CNI failed to parse ip from output %s due to %v", output, err) - } - - return ip, nil -} - -// GetPodIP gets the IP of the pod by inspecting the network info inside the pod's network namespace. -// TODO (khenidak). The "primary ip" in dual stack world does not really exist. For now -// we are defaulting to v4 as primary -func GetPodIPs(execer utilexec.Interface, nsenterPath, netnsPath, interfaceName string) ([]net.IP, error) { - var ( - list []net.IP - errs []error - ) - for _, addrType := range []string{"-4", "-6"} { - if ip, err := getOnePodIP(execer, nsenterPath, netnsPath, interfaceName, addrType); err == nil { - list = append(list, ip) - } else { - errs = append(errs, err) - } - } - - if len(list) == 0 { - return nil, utilerrors.NewAggregate(errs) - } - return list, nil - -} - -type NoopPortMappingGetter struct{} - -func (*NoopPortMappingGetter) GetPodPortMappings(containerID string) ([]*hostport.PortMapping, error) { - return nil, nil -} - -// The PluginManager wraps a kubelet network plugin and provides synchronization -// for a given pod's network operations. Each pod's setup/teardown/status operations -// are synchronized against each other, but network operations of other pods can -// proceed in parallel. -type PluginManager struct { - // Network plugin being wrapped - plugin NetworkPlugin - - // Pod list and lock - podsLock sync.Mutex - pods map[string]*podLock -} - -func NewPluginManager(plugin NetworkPlugin) *PluginManager { - metrics.Register() - return &PluginManager{ - plugin: plugin, - pods: make(map[string]*podLock), - } -} - -func (pm *PluginManager) PluginName() string { - return pm.plugin.Name() -} - -func (pm *PluginManager) Event(name string, details map[string]interface{}) { - pm.plugin.Event(name, details) -} - -func (pm *PluginManager) Status() error { - return pm.plugin.Status() -} - -type podLock struct { - // Count of in-flight operations for this pod; when this reaches zero - // the lock can be removed from the pod map - refcount uint - - // Lock to synchronize operations for this specific pod - mu sync.Mutex -} - -// Lock network operations for a specific pod. If that pod is not yet in -// the pod map, it will be added. The reference count for the pod will -// be increased. -func (pm *PluginManager) podLock(fullPodName string) *sync.Mutex { - pm.podsLock.Lock() - defer pm.podsLock.Unlock() - - lock, ok := pm.pods[fullPodName] - if !ok { - lock = &podLock{} - pm.pods[fullPodName] = lock - } - lock.refcount++ - return &lock.mu -} - -// Unlock network operations for a specific pod. The reference count for the -// pod will be decreased. If the reference count reaches zero, the pod will be -// removed from the pod map. -func (pm *PluginManager) podUnlock(fullPodName string) { - pm.podsLock.Lock() - defer pm.podsLock.Unlock() - - lock, ok := pm.pods[fullPodName] - if !ok { - klog.InfoS("Unbalanced pod lock unref for the pod", "podFullName", fullPodName) - return - } else if lock.refcount == 0 { - // This should never ever happen, but handle it anyway - delete(pm.pods, fullPodName) - klog.InfoS("Pod lock for the pod still in map with zero refcount", "podFullName", fullPodName) - return - } - lock.refcount-- - lock.mu.Unlock() - if lock.refcount == 0 { - delete(pm.pods, fullPodName) - } -} - -// recordOperation records operation and duration -func recordOperation(operation string, start time.Time) { - metrics.NetworkPluginOperations.WithLabelValues(operation).Inc() - metrics.NetworkPluginOperationsLatency.WithLabelValues(operation).Observe(metrics.SinceInSeconds(start)) -} - -// recordError records errors for metric. -func recordError(operation string) { - metrics.NetworkPluginOperationsErrors.WithLabelValues(operation).Inc() -} - -func (pm *PluginManager) GetPodNetworkStatus(podNamespace, podName string, id kubecontainer.ContainerID) (*PodNetworkStatus, error) { - const operation = "get_pod_network_status" - defer recordOperation(operation, time.Now()) - fullPodName := kubecontainer.BuildPodFullName(podName, podNamespace) - pm.podLock(fullPodName).Lock() - defer pm.podUnlock(fullPodName) - - netStatus, err := pm.plugin.GetPodNetworkStatus(podNamespace, podName, id) - if err != nil { - recordError(operation) - return nil, fmt.Errorf("networkPlugin %s failed on the status hook for pod %q: %v", pm.plugin.Name(), fullPodName, err) - } - - return netStatus, nil -} - -func (pm *PluginManager) SetUpPod(podNamespace, podName string, id kubecontainer.ContainerID, annotations, options map[string]string) error { - const operation = "set_up_pod" - defer recordOperation(operation, time.Now()) - fullPodName := kubecontainer.BuildPodFullName(podName, podNamespace) - pm.podLock(fullPodName).Lock() - defer pm.podUnlock(fullPodName) - - klog.V(3).InfoS("Calling network plugin to set up the pod", "pod", klog.KRef(podNamespace, podName), "networkPluginName", pm.plugin.Name()) - if err := pm.plugin.SetUpPod(podNamespace, podName, id, annotations, options); err != nil { - recordError(operation) - return fmt.Errorf("networkPlugin %s failed to set up pod %q network: %v", pm.plugin.Name(), fullPodName, err) - } - - return nil -} - -func (pm *PluginManager) TearDownPod(podNamespace, podName string, id kubecontainer.ContainerID) error { - const operation = "tear_down_pod" - defer recordOperation(operation, time.Now()) - fullPodName := kubecontainer.BuildPodFullName(podName, podNamespace) - pm.podLock(fullPodName).Lock() - defer pm.podUnlock(fullPodName) - - klog.V(3).InfoS("Calling network plugin to tear down the pod", "pod", klog.KRef(podNamespace, podName), "networkPluginName", pm.plugin.Name()) - if err := pm.plugin.TearDownPod(podNamespace, podName, id); err != nil { - recordError(operation) - return fmt.Errorf("networkPlugin %s failed to teardown pod %q network: %v", pm.plugin.Name(), fullPodName, err) - } - - return nil -} diff --git a/pkg/kubelet/dockershim/network/plugins_test.go b/pkg/kubelet/dockershim/network/plugins_test.go deleted file mode 100644 index 286cd6f44b7..00000000000 --- a/pkg/kubelet/dockershim/network/plugins_test.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package network - -import ( - "strings" - "testing" - "time" - - "k8s.io/component-base/metrics/legacyregistry" - "k8s.io/component-base/metrics/testutil" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics" -) - -func TestNetworkPluginManagerMetrics(t *testing.T) { - metrics.Register() - defer legacyregistry.Reset() - - operation := "test_operation" - recordOperation(operation, time.Now()) - recordError(operation) - - cases := []struct { - metricName string - want string - }{ - { - metricName: "kubelet_network_plugin_operations_total", - want: ` -# HELP kubelet_network_plugin_operations_total [ALPHA] Cumulative number of network plugin operations by operation type. -# TYPE kubelet_network_plugin_operations_total counter -kubelet_network_plugin_operations_total{operation_type="test_operation"} 1 -`, - }, - { - metricName: "kubelet_network_plugin_operations_errors_total", - want: ` -# HELP kubelet_network_plugin_operations_errors_total [ALPHA] Cumulative number of network plugin operation errors by operation type. -# TYPE kubelet_network_plugin_operations_errors_total counter -kubelet_network_plugin_operations_errors_total{operation_type="test_operation"} 1 -`, - }, - } - - for _, tc := range cases { - t.Run(tc.metricName, func(t *testing.T) { - if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tc.want), tc.metricName); err != nil { - t.Fatal(err) - } - }) - } -} diff --git a/pkg/kubelet/dockershim/network/testing/fake_host.go b/pkg/kubelet/dockershim/network/testing/fake_host.go deleted file mode 100644 index c3d415be03a..00000000000 --- a/pkg/kubelet/dockershim/network/testing/fake_host.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package testing - -// helper for testing plugins -// a fake host is created here that can be used by plugins for testing - -import ( - "k8s.io/api/core/v1" - clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" -) - -type fakeNetworkHost struct { - fakeNamespaceGetter - FakePortMappingGetter - kubeClient clientset.Interface - Legacy bool -} - -func NewFakeHost(kubeClient clientset.Interface) *fakeNetworkHost { - host := &fakeNetworkHost{kubeClient: kubeClient, Legacy: true} - return host -} - -func (fnh *fakeNetworkHost) GetPodByName(name, namespace string) (*v1.Pod, bool) { - return nil, false -} - -func (fnh *fakeNetworkHost) GetKubeClient() clientset.Interface { - return nil -} - -func (nh *fakeNetworkHost) SupportsLegacyFeatures() bool { - return nh.Legacy -} - -type fakeNamespaceGetter struct { - ns string -} - -func (nh *fakeNamespaceGetter) GetNetNS(containerID string) (string, error) { - return nh.ns, nil -} - -type FakePortMappingGetter struct { - PortMaps map[string][]*hostport.PortMapping -} - -func (pm *FakePortMappingGetter) GetPodPortMappings(containerID string) ([]*hostport.PortMapping, error) { - return pm.PortMaps[containerID], nil -} diff --git a/pkg/kubelet/dockershim/network/testing/mock_network_plugin.go b/pkg/kubelet/dockershim/network/testing/mock_network_plugin.go deleted file mode 100644 index 6691d19fb3f..00000000000 --- a/pkg/kubelet/dockershim/network/testing/mock_network_plugin.go +++ /dev/null @@ -1,297 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright The Kubernetes 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. -*/ - -// Code generated by MockGen. DO NOT EDIT. -// Source: plugins.go - -// Package testing is a generated GoMock package. -package testing - -import ( - gomock "github.com/golang/mock/gomock" - sets "k8s.io/apimachinery/pkg/util/sets" - config "k8s.io/kubernetes/pkg/kubelet/apis/config" - container "k8s.io/kubernetes/pkg/kubelet/container" - network "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - hostport "k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport" - reflect "reflect" -) - -// MockNetworkPlugin is a mock of NetworkPlugin interface -type MockNetworkPlugin struct { - ctrl *gomock.Controller - recorder *MockNetworkPluginMockRecorder -} - -// MockNetworkPluginMockRecorder is the mock recorder for MockNetworkPlugin -type MockNetworkPluginMockRecorder struct { - mock *MockNetworkPlugin -} - -// NewMockNetworkPlugin creates a new mock instance -func NewMockNetworkPlugin(ctrl *gomock.Controller) *MockNetworkPlugin { - mock := &MockNetworkPlugin{ctrl: ctrl} - mock.recorder = &MockNetworkPluginMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockNetworkPlugin) EXPECT() *MockNetworkPluginMockRecorder { - return m.recorder -} - -// Init mocks base method -func (m *MockNetworkPlugin) Init(host network.Host, hairpinMode config.HairpinMode, nonMasqueradeCIDR string, mtu int) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Init", host, hairpinMode, nonMasqueradeCIDR, mtu) - ret0, _ := ret[0].(error) - return ret0 -} - -// Init indicates an expected call of Init -func (mr *MockNetworkPluginMockRecorder) Init(host, hairpinMode, nonMasqueradeCIDR, mtu interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockNetworkPlugin)(nil).Init), host, hairpinMode, nonMasqueradeCIDR, mtu) -} - -// Event mocks base method -func (m *MockNetworkPlugin) Event(name string, details map[string]interface{}) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Event", name, details) -} - -// Event indicates an expected call of Event -func (mr *MockNetworkPluginMockRecorder) Event(name, details interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Event", reflect.TypeOf((*MockNetworkPlugin)(nil).Event), name, details) -} - -// Name mocks base method -func (m *MockNetworkPlugin) Name() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Name") - ret0, _ := ret[0].(string) - return ret0 -} - -// Name indicates an expected call of Name -func (mr *MockNetworkPluginMockRecorder) Name() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockNetworkPlugin)(nil).Name)) -} - -// Capabilities mocks base method -func (m *MockNetworkPlugin) Capabilities() sets.Int { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Capabilities") - ret0, _ := ret[0].(sets.Int) - return ret0 -} - -// Capabilities indicates an expected call of Capabilities -func (mr *MockNetworkPluginMockRecorder) Capabilities() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Capabilities", reflect.TypeOf((*MockNetworkPlugin)(nil).Capabilities)) -} - -// SetUpPod mocks base method -func (m *MockNetworkPlugin) SetUpPod(namespace, name string, podSandboxID container.ContainerID, annotations, options map[string]string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetUpPod", namespace, name, podSandboxID, annotations, options) - ret0, _ := ret[0].(error) - return ret0 -} - -// SetUpPod indicates an expected call of SetUpPod -func (mr *MockNetworkPluginMockRecorder) SetUpPod(namespace, name, podSandboxID, annotations, options interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetUpPod", reflect.TypeOf((*MockNetworkPlugin)(nil).SetUpPod), namespace, name, podSandboxID, annotations, options) -} - -// TearDownPod mocks base method -func (m *MockNetworkPlugin) TearDownPod(namespace, name string, podSandboxID container.ContainerID) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TearDownPod", namespace, name, podSandboxID) - ret0, _ := ret[0].(error) - return ret0 -} - -// TearDownPod indicates an expected call of TearDownPod -func (mr *MockNetworkPluginMockRecorder) TearDownPod(namespace, name, podSandboxID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TearDownPod", reflect.TypeOf((*MockNetworkPlugin)(nil).TearDownPod), namespace, name, podSandboxID) -} - -// GetPodNetworkStatus mocks base method -func (m *MockNetworkPlugin) GetPodNetworkStatus(namespace, name string, podSandboxID container.ContainerID) (*network.PodNetworkStatus, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPodNetworkStatus", namespace, name, podSandboxID) - ret0, _ := ret[0].(*network.PodNetworkStatus) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPodNetworkStatus indicates an expected call of GetPodNetworkStatus -func (mr *MockNetworkPluginMockRecorder) GetPodNetworkStatus(namespace, name, podSandboxID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPodNetworkStatus", reflect.TypeOf((*MockNetworkPlugin)(nil).GetPodNetworkStatus), namespace, name, podSandboxID) -} - -// Status mocks base method -func (m *MockNetworkPlugin) Status() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Status") - ret0, _ := ret[0].(error) - return ret0 -} - -// Status indicates an expected call of Status -func (mr *MockNetworkPluginMockRecorder) Status() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockNetworkPlugin)(nil).Status)) -} - -// MockHost is a mock of Host interface -type MockHost struct { - ctrl *gomock.Controller - recorder *MockHostMockRecorder -} - -// MockHostMockRecorder is the mock recorder for MockHost -type MockHostMockRecorder struct { - mock *MockHost -} - -// NewMockHost creates a new mock instance -func NewMockHost(ctrl *gomock.Controller) *MockHost { - mock := &MockHost{ctrl: ctrl} - mock.recorder = &MockHostMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockHost) EXPECT() *MockHostMockRecorder { - return m.recorder -} - -// GetNetNS mocks base method -func (m *MockHost) GetNetNS(containerID string) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNetNS", containerID) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetNetNS indicates an expected call of GetNetNS -func (mr *MockHostMockRecorder) GetNetNS(containerID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetNS", reflect.TypeOf((*MockHost)(nil).GetNetNS), containerID) -} - -// GetPodPortMappings mocks base method -func (m *MockHost) GetPodPortMappings(containerID string) ([]*hostport.PortMapping, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPodPortMappings", containerID) - ret0, _ := ret[0].([]*hostport.PortMapping) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPodPortMappings indicates an expected call of GetPodPortMappings -func (mr *MockHostMockRecorder) GetPodPortMappings(containerID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPodPortMappings", reflect.TypeOf((*MockHost)(nil).GetPodPortMappings), containerID) -} - -// MockNamespaceGetter is a mock of NamespaceGetter interface -type MockNamespaceGetter struct { - ctrl *gomock.Controller - recorder *MockNamespaceGetterMockRecorder -} - -// MockNamespaceGetterMockRecorder is the mock recorder for MockNamespaceGetter -type MockNamespaceGetterMockRecorder struct { - mock *MockNamespaceGetter -} - -// NewMockNamespaceGetter creates a new mock instance -func NewMockNamespaceGetter(ctrl *gomock.Controller) *MockNamespaceGetter { - mock := &MockNamespaceGetter{ctrl: ctrl} - mock.recorder = &MockNamespaceGetterMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockNamespaceGetter) EXPECT() *MockNamespaceGetterMockRecorder { - return m.recorder -} - -// GetNetNS mocks base method -func (m *MockNamespaceGetter) GetNetNS(containerID string) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNetNS", containerID) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetNetNS indicates an expected call of GetNetNS -func (mr *MockNamespaceGetterMockRecorder) GetNetNS(containerID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetNS", reflect.TypeOf((*MockNamespaceGetter)(nil).GetNetNS), containerID) -} - -// MockPortMappingGetter is a mock of PortMappingGetter interface -type MockPortMappingGetter struct { - ctrl *gomock.Controller - recorder *MockPortMappingGetterMockRecorder -} - -// MockPortMappingGetterMockRecorder is the mock recorder for MockPortMappingGetter -type MockPortMappingGetterMockRecorder struct { - mock *MockPortMappingGetter -} - -// NewMockPortMappingGetter creates a new mock instance -func NewMockPortMappingGetter(ctrl *gomock.Controller) *MockPortMappingGetter { - mock := &MockPortMappingGetter{ctrl: ctrl} - mock.recorder = &MockPortMappingGetterMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockPortMappingGetter) EXPECT() *MockPortMappingGetterMockRecorder { - return m.recorder -} - -// GetPodPortMappings mocks base method -func (m *MockPortMappingGetter) GetPodPortMappings(containerID string) ([]*hostport.PortMapping, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPodPortMappings", containerID) - ret0, _ := ret[0].([]*hostport.PortMapping) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPodPortMappings indicates an expected call of GetPodPortMappings -func (mr *MockPortMappingGetterMockRecorder) GetPodPortMappings(containerID interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPodPortMappings", reflect.TypeOf((*MockPortMappingGetter)(nil).GetPodPortMappings), containerID) -} diff --git a/pkg/kubelet/dockershim/network/testing/plugins_test.go b/pkg/kubelet/dockershim/network/testing/plugins_test.go deleted file mode 100644 index 3a6cc61d77a..00000000000 --- a/pkg/kubelet/dockershim/network/testing/plugins_test.go +++ /dev/null @@ -1,252 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package testing - -import ( - "fmt" - "sync" - "testing" - - utilsets "k8s.io/apimachinery/pkg/util/sets" - sysctltest "k8s.io/component-helpers/node/util/sysctl/testing" - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - "k8s.io/kubernetes/pkg/kubelet/dockershim/network" - netutils "k8s.io/utils/net" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestSelectDefaultPlugin(t *testing.T) { - all_plugins := []network.NetworkPlugin{} - plug, err := network.InitNetworkPlugin(all_plugins, "", NewFakeHost(nil), kubeletconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU) - if err != nil { - t.Fatalf("Unexpected error in selecting default plugin: %v", err) - } - if plug == nil { - t.Fatalf("Failed to select the default plugin.") - } - if plug.Name() != network.DefaultPluginName { - t.Errorf("Failed to select the default plugin. Expected %s. Got %s", network.DefaultPluginName, plug.Name()) - } -} - -func TestInit(t *testing.T) { - tests := []struct { - setting string - expectedLen int - }{ - { - setting: "net/bridge/bridge-nf-call-iptables", - expectedLen: 1, - }, - { - setting: "net/bridge/bridge-nf-call-ip6tables", - expectedLen: 2, - }, - } - for _, tt := range tests { - sysctl := sysctltest.NewFake() - sysctl.Settings[tt.setting] = 0 - plug := &network.NoopNetworkPlugin{} - plug.Sysctl = sysctl - plug.Init(NewFakeHost(nil), kubeletconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU) - // Verify the sysctl specified is set - assert.Equal(t, 1, sysctl.Settings[tt.setting], tt.setting+" sysctl should have been set") - // Verify iptables is always set - assert.Equal(t, 1, sysctl.Settings["net/bridge/bridge-nf-call-iptables"], "net/bridge/bridge-nf-call-iptables sysctl should have been set") - // Verify ip6tables is only set if it existed - assert.Len(t, sysctl.Settings, tt.expectedLen, "length wrong for "+tt.setting) - } -} - -func TestPluginManager(t *testing.T) { - ctrl := gomock.NewController(t) - fnp := NewMockNetworkPlugin(ctrl) - defer ctrl.Finish() - pm := network.NewPluginManager(fnp) - - fnp.EXPECT().Name().Return("someNetworkPlugin").AnyTimes() - - allCreatedWg := sync.WaitGroup{} - allCreatedWg.Add(1) - allDoneWg := sync.WaitGroup{} - - // 10 pods, 4 setup/status/teardown runs each. Ensure that network locking - // works and the pod map isn't concurrently accessed - for i := 0; i < 10; i++ { - podName := fmt.Sprintf("pod%d", i) - containerID := kubecontainer.ContainerID{ID: podName} - - fnp.EXPECT().SetUpPod("", podName, containerID, nil, nil).Return(nil).Times(4) - fnp.EXPECT().GetPodNetworkStatus("", podName, containerID).Return(&network.PodNetworkStatus{IP: netutils.ParseIPSloppy("1.2.3.4")}, nil).Times(4) - fnp.EXPECT().TearDownPod("", podName, containerID).Return(nil).Times(4) - - for x := 0; x < 4; x++ { - allDoneWg.Add(1) - go func(name string, id kubecontainer.ContainerID, num int) { - defer allDoneWg.Done() - - // Block all goroutines from running until all have - // been created and are ready. This ensures we - // have more pod network operations running - // concurrently. - allCreatedWg.Wait() - - if err := pm.SetUpPod("", name, id, nil, nil); err != nil { - t.Errorf("Failed to set up pod %q: %v", name, err) - return - } - - if _, err := pm.GetPodNetworkStatus("", name, id); err != nil { - t.Errorf("Failed to inspect pod %q: %v", name, err) - return - } - - if err := pm.TearDownPod("", name, id); err != nil { - t.Errorf("Failed to tear down pod %q: %v", name, err) - return - } - }(podName, containerID, x) - } - } - // Block all goroutines from running until all have been created and started - allCreatedWg.Done() - - // Wait for them all to finish - allDoneWg.Wait() -} - -type hookableFakeNetworkPluginSetupHook func(namespace, name string, id kubecontainer.ContainerID) - -type hookableFakeNetworkPlugin struct { - setupHook hookableFakeNetworkPluginSetupHook -} - -func newHookableFakeNetworkPlugin(setupHook hookableFakeNetworkPluginSetupHook) *hookableFakeNetworkPlugin { - return &hookableFakeNetworkPlugin{ - setupHook: setupHook, - } -} - -func (p *hookableFakeNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { - return nil -} - -func (p *hookableFakeNetworkPlugin) Event(name string, details map[string]interface{}) { -} - -func (p *hookableFakeNetworkPlugin) Name() string { - return "fakeplugin" -} - -func (p *hookableFakeNetworkPlugin) Capabilities() utilsets.Int { - return utilsets.NewInt() -} - -func (p *hookableFakeNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations, options map[string]string) error { - if p.setupHook != nil { - p.setupHook(namespace, name, id) - } - return nil -} - -func (p *hookableFakeNetworkPlugin) TearDownPod(string, string, kubecontainer.ContainerID) error { - return nil -} - -func (p *hookableFakeNetworkPlugin) GetPodNetworkStatus(string, string, kubecontainer.ContainerID) (*network.PodNetworkStatus, error) { - return &network.PodNetworkStatus{IP: netutils.ParseIPSloppy("10.1.2.3")}, nil -} - -func (p *hookableFakeNetworkPlugin) Status() error { - return nil -} - -// Ensure that one pod's network operations don't block another's. If the -// test is successful (eg, first pod doesn't block on second) the test -// will complete. If unsuccessful, it will hang and get killed. -func TestMultiPodParallelNetworkOps(t *testing.T) { - podWg := sync.WaitGroup{} - podWg.Add(1) - - // Can't do this with MockNetworkPlugin because the gomock controller - // has its own locks which don't allow the parallel network operation - // to proceed. - didWait := false - fakePlugin := newHookableFakeNetworkPlugin(func(podNamespace, podName string, id kubecontainer.ContainerID) { - if podName == "waiter" { - podWg.Wait() - didWait = true - } - }) - pm := network.NewPluginManager(fakePlugin) - - opsWg := sync.WaitGroup{} - - // Start the pod that will wait for the other to complete - opsWg.Add(1) - go func() { - defer opsWg.Done() - - podName := "waiter" - containerID := kubecontainer.ContainerID{ID: podName} - - // Setup will block on the runner pod completing. If network - // operations locking isn't correct (eg pod network operations - // block other pods) setUpPod() will never return. - if err := pm.SetUpPod("", podName, containerID, nil, nil); err != nil { - t.Errorf("Failed to set up waiter pod: %v", err) - return - } - - if err := pm.TearDownPod("", podName, containerID); err != nil { - t.Errorf("Failed to tear down waiter pod: %v", err) - return - } - }() - - opsWg.Add(1) - go func() { - defer opsWg.Done() - // Let other pod proceed - defer podWg.Done() - - podName := "runner" - containerID := kubecontainer.ContainerID{ID: podName} - - if err := pm.SetUpPod("", podName, containerID, nil, nil); err != nil { - t.Errorf("Failed to set up runner pod: %v", err) - return - } - - if err := pm.TearDownPod("", podName, containerID); err != nil { - t.Errorf("Failed to tear down runner pod: %v", err) - return - } - }() - - opsWg.Wait() - - if !didWait { - t.Errorf("waiter pod didn't wait for runner pod!") - } -} diff --git a/pkg/kubelet/dockershim/remote/docker_server.go b/pkg/kubelet/dockershim/remote/docker_server.go deleted file mode 100644 index 433f53890e0..00000000000 --- a/pkg/kubelet/dockershim/remote/docker_server.go +++ /dev/null @@ -1,82 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package remote - -import ( - "fmt" - "os" - - "google.golang.org/grpc" - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/klog/v2" - "k8s.io/kubernetes/pkg/kubelet/dockershim" - "k8s.io/kubernetes/pkg/kubelet/util" -) - -// maxMsgSize use 16MB as the default message size limit. -// grpc library default is 4MB -const maxMsgSize = 1024 * 1024 * 16 - -// DockerServer is the grpc server of dockershim. -type DockerServer struct { - // endpoint is the endpoint to serve on. - endpoint string - // service is the docker service which implements runtime and image services. - service dockershim.CRIService - // server is the grpc server. - server *grpc.Server -} - -// NewDockerServer creates the dockershim grpc server. -func NewDockerServer(endpoint string, s dockershim.CRIService) *DockerServer { - return &DockerServer{ - endpoint: endpoint, - service: s, - } -} - -// Start starts the dockershim grpc server. -func (s *DockerServer) Start() error { - // Start the internal service. - if err := s.service.Start(); err != nil { - klog.ErrorS(err, "Unable to start docker service") - return err - } - - klog.V(2).InfoS("Start dockershim grpc server") - l, err := util.CreateListener(s.endpoint) - if err != nil { - return fmt.Errorf("failed to listen on %q: %v", s.endpoint, err) - } - // Create the grpc server and register runtime and image services. - s.server = grpc.NewServer( - grpc.MaxRecvMsgSize(maxMsgSize), - grpc.MaxSendMsgSize(maxMsgSize), - ) - runtimeapi.RegisterRuntimeServiceServer(s.server, s.service) - runtimeapi.RegisterImageServiceServer(s.server, s.service) - go func() { - if err := s.server.Serve(l); err != nil { - klog.ErrorS(err, "Failed to serve connections") - os.Exit(1) - } - }() - return nil -} diff --git a/pkg/kubelet/dockershim/remote/docker_server_test.go b/pkg/kubelet/dockershim/remote/docker_server_test.go deleted file mode 100644 index 6cecb514aa8..00000000000 --- a/pkg/kubelet/dockershim/remote/docker_server_test.go +++ /dev/null @@ -1,174 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package remote - -import ( - "context" - "io/ioutil" - "testing" - - "github.com/stretchr/testify/assert" - "google.golang.org/grpc" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -func TestServer(t *testing.T) { - file, err := ioutil.TempFile("", "docker-server-") - assert.Nil(t, err) - endpoint := "unix://" + file.Name() - - server := NewDockerServer(endpoint, &fakeCRIService{}) - assert.Nil(t, server.Start()) - - ctx := context.Background() - conn, err := grpc.Dial(endpoint, grpc.WithInsecure()) - assert.Nil(t, err) - - runtimeClient := runtimeapi.NewRuntimeServiceClient(conn) - _, err = runtimeClient.Version(ctx, &runtimeapi.VersionRequest{}) - assert.Nil(t, err) - - imageClient := runtimeapi.NewImageServiceClient(conn) - _, err = imageClient.ImageFsInfo(ctx, &runtimeapi.ImageFsInfoRequest{}) - assert.Nil(t, err) -} - -type fakeCRIService struct{} - -func (*fakeCRIService) Start() error { - return nil -} - -func (*fakeCRIService) Version(context.Context, *runtimeapi.VersionRequest) (*runtimeapi.VersionResponse, error) { - return &runtimeapi.VersionResponse{}, nil -} - -func (*fakeCRIService) RunPodSandbox(context.Context, *runtimeapi.RunPodSandboxRequest) (*runtimeapi.RunPodSandboxResponse, error) { - return nil, nil -} - -func (*fakeCRIService) StopPodSandbox(context.Context, *runtimeapi.StopPodSandboxRequest) (*runtimeapi.StopPodSandboxResponse, error) { - return nil, nil -} - -func (*fakeCRIService) RemovePodSandbox(context.Context, *runtimeapi.RemovePodSandboxRequest) (*runtimeapi.RemovePodSandboxResponse, error) { - return nil, nil -} - -func (*fakeCRIService) PodSandboxStatus(context.Context, *runtimeapi.PodSandboxStatusRequest) (*runtimeapi.PodSandboxStatusResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ListPodSandbox(context.Context, *runtimeapi.ListPodSandboxRequest) (*runtimeapi.ListPodSandboxResponse, error) { - return nil, nil -} - -func (*fakeCRIService) CreateContainer(context.Context, *runtimeapi.CreateContainerRequest) (*runtimeapi.CreateContainerResponse, error) { - return nil, nil -} - -func (*fakeCRIService) StartContainer(context.Context, *runtimeapi.StartContainerRequest) (*runtimeapi.StartContainerResponse, error) { - return nil, nil -} - -func (*fakeCRIService) StopContainer(context.Context, *runtimeapi.StopContainerRequest) (*runtimeapi.StopContainerResponse, error) { - return nil, nil -} - -func (*fakeCRIService) RemoveContainer(context.Context, *runtimeapi.RemoveContainerRequest) (*runtimeapi.RemoveContainerResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ListContainers(context.Context, *runtimeapi.ListContainersRequest) (*runtimeapi.ListContainersResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ContainerStatus(context.Context, *runtimeapi.ContainerStatusRequest) (*runtimeapi.ContainerStatusResponse, error) { - return nil, nil -} - -func (*fakeCRIService) UpdateContainerResources(context.Context, *runtimeapi.UpdateContainerResourcesRequest) (*runtimeapi.UpdateContainerResourcesResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ReopenContainerLog(context.Context, *runtimeapi.ReopenContainerLogRequest) (*runtimeapi.ReopenContainerLogResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ExecSync(context.Context, *runtimeapi.ExecSyncRequest) (*runtimeapi.ExecSyncResponse, error) { - return nil, nil -} - -func (*fakeCRIService) Exec(context.Context, *runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error) { - return nil, nil -} - -func (*fakeCRIService) Attach(context.Context, *runtimeapi.AttachRequest) (*runtimeapi.AttachResponse, error) { - return nil, nil -} - -func (*fakeCRIService) PortForward(context.Context, *runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ContainerStats(context.Context, *runtimeapi.ContainerStatsRequest) (*runtimeapi.ContainerStatsResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ListContainerStats(context.Context, *runtimeapi.ListContainerStatsRequest) (*runtimeapi.ListContainerStatsResponse, error) { - return nil, nil -} - -func (*fakeCRIService) PodSandboxStats(context.Context, *runtimeapi.PodSandboxStatsRequest) (*runtimeapi.PodSandboxStatsResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ListPodSandboxStats(context.Context, *runtimeapi.ListPodSandboxStatsRequest) (*runtimeapi.ListPodSandboxStatsResponse, error) { - return nil, nil -} - -func (*fakeCRIService) UpdateRuntimeConfig(context.Context, *runtimeapi.UpdateRuntimeConfigRequest) (*runtimeapi.UpdateRuntimeConfigResponse, error) { - return nil, nil -} - -func (*fakeCRIService) Status(context.Context, *runtimeapi.StatusRequest) (*runtimeapi.StatusResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ListImages(context.Context, *runtimeapi.ListImagesRequest) (*runtimeapi.ListImagesResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ImageStatus(context.Context, *runtimeapi.ImageStatusRequest) (*runtimeapi.ImageStatusResponse, error) { - return nil, nil -} - -func (*fakeCRIService) PullImage(context.Context, *runtimeapi.PullImageRequest) (*runtimeapi.PullImageResponse, error) { - return nil, nil -} - -func (*fakeCRIService) RemoveImage(context.Context, *runtimeapi.RemoveImageRequest) (*runtimeapi.RemoveImageResponse, error) { - return nil, nil -} - -func (*fakeCRIService) ImageFsInfo(context.Context, *runtimeapi.ImageFsInfoRequest) (*runtimeapi.ImageFsInfoResponse, error) { - return &runtimeapi.ImageFsInfoResponse{}, nil -} diff --git a/pkg/kubelet/dockershim/security_context.go b/pkg/kubelet/dockershim/security_context.go deleted file mode 100644 index 25a12c450eb..00000000000 --- a/pkg/kubelet/dockershim/security_context.go +++ /dev/null @@ -1,207 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - "strconv" - - dockercontainer "github.com/docker/docker/api/types/container" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - knetwork "k8s.io/kubernetes/pkg/kubelet/dockershim/network" -) - -// applySandboxSecurityContext updates docker sandbox options according to security context. -func applySandboxSecurityContext(lc *runtimeapi.LinuxPodSandboxConfig, config *dockercontainer.Config, hc *dockercontainer.HostConfig, network *knetwork.PluginManager, separator rune) error { - if lc == nil { - return nil - } - - var sc *runtimeapi.LinuxContainerSecurityContext - if lc.SecurityContext != nil { - sc = &runtimeapi.LinuxContainerSecurityContext{ - SupplementalGroups: lc.SecurityContext.SupplementalGroups, - RunAsUser: lc.SecurityContext.RunAsUser, - RunAsGroup: lc.SecurityContext.RunAsGroup, - ReadonlyRootfs: lc.SecurityContext.ReadonlyRootfs, - SelinuxOptions: lc.SecurityContext.SelinuxOptions, - NamespaceOptions: lc.SecurityContext.NamespaceOptions, - Privileged: lc.SecurityContext.Privileged, - } - } - - err := modifyContainerConfig(sc, config) - if err != nil { - return err - } - - if err := modifyHostConfig(sc, hc, separator); err != nil { - return err - } - modifySandboxNamespaceOptions(sc.GetNamespaceOptions(), hc, network) - return nil -} - -// applyContainerSecurityContext updates docker container options according to security context. -func applyContainerSecurityContext(lc *runtimeapi.LinuxContainerConfig, podSandboxID string, config *dockercontainer.Config, hc *dockercontainer.HostConfig, separator rune) error { - if lc == nil { - return nil - } - - err := modifyContainerConfig(lc.SecurityContext, config) - if err != nil { - return err - } - if err := modifyHostConfig(lc.SecurityContext, hc, separator); err != nil { - return err - } - modifyContainerNamespaceOptions(lc.SecurityContext.GetNamespaceOptions(), podSandboxID, hc) - return nil -} - -// modifyContainerConfig applies container security context config to dockercontainer.Config. -func modifyContainerConfig(sc *runtimeapi.LinuxContainerSecurityContext, config *dockercontainer.Config) error { - if sc == nil { - return nil - } - if sc.RunAsUser != nil { - config.User = strconv.FormatInt(sc.GetRunAsUser().Value, 10) - } - if sc.RunAsUsername != "" { - config.User = sc.RunAsUsername - } - - user := config.User - if sc.RunAsGroup != nil { - if user == "" { - return fmt.Errorf("runAsGroup is specified without a runAsUser") - } - user = fmt.Sprintf("%s:%d", config.User, sc.GetRunAsGroup().Value) - } - - config.User = user - - return nil -} - -// modifyHostConfig applies security context config to dockercontainer.HostConfig. -func modifyHostConfig(sc *runtimeapi.LinuxContainerSecurityContext, hostConfig *dockercontainer.HostConfig, separator rune) error { - if sc == nil { - return nil - } - - // Apply supplemental groups. - for _, group := range sc.SupplementalGroups { - hostConfig.GroupAdd = append(hostConfig.GroupAdd, strconv.FormatInt(group, 10)) - } - - // Apply security context for the container. - hostConfig.Privileged = sc.Privileged - hostConfig.ReadonlyRootfs = sc.ReadonlyRootfs - if sc.Capabilities != nil { - hostConfig.CapAdd = sc.GetCapabilities().AddCapabilities - hostConfig.CapDrop = sc.GetCapabilities().DropCapabilities - } - if sc.SelinuxOptions != nil { - hostConfig.SecurityOpt = addSELinuxOptions( - hostConfig.SecurityOpt, - sc.SelinuxOptions, - separator, - ) - } - - // Apply apparmor options. - apparmorSecurityOpts, err := getApparmorSecurityOpts(sc, separator) - if err != nil { - return fmt.Errorf("failed to generate apparmor security options: %v", err) - } - hostConfig.SecurityOpt = append(hostConfig.SecurityOpt, apparmorSecurityOpts...) - - if sc.NoNewPrivs { - hostConfig.SecurityOpt = append(hostConfig.SecurityOpt, "no-new-privileges") - } - - if !hostConfig.Privileged { - hostConfig.MaskedPaths = sc.MaskedPaths - hostConfig.ReadonlyPaths = sc.ReadonlyPaths - } - - return nil -} - -// modifySandboxNamespaceOptions apply namespace options for sandbox -func modifySandboxNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, hostConfig *dockercontainer.HostConfig, network *knetwork.PluginManager) { - // The sandbox's PID namespace is the one that's shared, so CONTAINER and POD are equivalent for it - if nsOpts.GetPid() == runtimeapi.NamespaceMode_NODE { - hostConfig.PidMode = namespaceModeHost - } - modifyHostOptionsForSandbox(nsOpts, network, hostConfig) -} - -// modifyContainerNamespaceOptions apply namespace options for container -func modifyContainerNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, podSandboxID string, hostConfig *dockercontainer.HostConfig) { - switch nsOpts.GetPid() { - case runtimeapi.NamespaceMode_NODE: - hostConfig.PidMode = namespaceModeHost - case runtimeapi.NamespaceMode_POD: - hostConfig.PidMode = dockercontainer.PidMode(fmt.Sprintf("container:%v", podSandboxID)) - case runtimeapi.NamespaceMode_TARGET: - hostConfig.PidMode = dockercontainer.PidMode(fmt.Sprintf("container:%v", nsOpts.GetTargetId())) - } - modifyHostOptionsForContainer(nsOpts, podSandboxID, hostConfig) -} - -// modifyHostOptionsForSandbox applies NetworkMode/UTSMode to sandbox's dockercontainer.HostConfig. -func modifyHostOptionsForSandbox(nsOpts *runtimeapi.NamespaceOption, network *knetwork.PluginManager, hc *dockercontainer.HostConfig) { - if nsOpts.GetIpc() == runtimeapi.NamespaceMode_NODE { - hc.IpcMode = namespaceModeHost - } - if nsOpts.GetNetwork() == runtimeapi.NamespaceMode_NODE { - hc.NetworkMode = namespaceModeHost - return - } - - if network == nil { - hc.NetworkMode = "default" - return - } - - switch network.PluginName() { - case "cni": - fallthrough - case "kubenet": - hc.NetworkMode = "none" - default: - hc.NetworkMode = "default" - } -} - -// modifyHostOptionsForContainer applies NetworkMode/UTSMode to container's dockercontainer.HostConfig. -func modifyHostOptionsForContainer(nsOpts *runtimeapi.NamespaceOption, podSandboxID string, hc *dockercontainer.HostConfig) { - sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID) - hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode) - hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode) - hc.UTSMode = "" - - if nsOpts.GetNetwork() == runtimeapi.NamespaceMode_NODE { - hc.UTSMode = namespaceModeHost - } -} diff --git a/pkg/kubelet/dockershim/security_context_test.go b/pkg/kubelet/dockershim/security_context_test.go deleted file mode 100644 index 01f46fa1b52..00000000000 --- a/pkg/kubelet/dockershim/security_context_test.go +++ /dev/null @@ -1,494 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - "strconv" - "testing" - - dockercontainer "github.com/docker/docker/api/types/container" - "github.com/stretchr/testify/assert" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -func TestModifyContainerConfig(t *testing.T) { - var uid int64 = 123 - var username = "testuser" - var gid int64 = 423 - - cases := []struct { - name string - sc *runtimeapi.LinuxContainerSecurityContext - expected *dockercontainer.Config - isErr bool - }{ - { - name: "container.SecurityContext.RunAsUser set", - sc: &runtimeapi.LinuxContainerSecurityContext{ - RunAsUser: &runtimeapi.Int64Value{Value: uid}, - }, - expected: &dockercontainer.Config{ - User: strconv.FormatInt(uid, 10), - }, - isErr: false, - }, - { - name: "container.SecurityContext.RunAsUsername set", - sc: &runtimeapi.LinuxContainerSecurityContext{ - RunAsUsername: username, - }, - expected: &dockercontainer.Config{ - User: username, - }, - isErr: false, - }, - { - name: "container.SecurityContext.RunAsUsername and container.SecurityContext.RunAsUser set", - sc: &runtimeapi.LinuxContainerSecurityContext{ - RunAsUsername: username, - RunAsUser: &runtimeapi.Int64Value{Value: uid}, - }, - expected: &dockercontainer.Config{ - User: username, - }, - isErr: false, - }, - - { - name: "no RunAsUser value set", - sc: &runtimeapi.LinuxContainerSecurityContext{}, - expected: &dockercontainer.Config{}, - isErr: false, - }, - { - name: "RunAsUser value set, RunAsGroup set", - sc: &runtimeapi.LinuxContainerSecurityContext{ - RunAsUser: &runtimeapi.Int64Value{Value: uid}, - RunAsGroup: &runtimeapi.Int64Value{Value: gid}, - }, - expected: &dockercontainer.Config{ - User: "123:423", - }, - isErr: false, - }, - { - name: "RunAsUsername value set, RunAsGroup set", - sc: &runtimeapi.LinuxContainerSecurityContext{ - RunAsUsername: username, - RunAsGroup: &runtimeapi.Int64Value{Value: gid}, - }, - expected: &dockercontainer.Config{ - User: "testuser:423", - }, - isErr: false, - }, - { - name: "RunAsUser/RunAsUsername not set, RunAsGroup set", - sc: &runtimeapi.LinuxContainerSecurityContext{ - RunAsGroup: &runtimeapi.Int64Value{Value: gid}, - }, - isErr: true, - }, - { - name: "RunAsUser/RunAsUsername both set, RunAsGroup set", - sc: &runtimeapi.LinuxContainerSecurityContext{ - RunAsUser: &runtimeapi.Int64Value{Value: uid}, - RunAsUsername: username, - RunAsGroup: &runtimeapi.Int64Value{Value: gid}, - }, - expected: &dockercontainer.Config{ - User: "testuser:423", - }, - isErr: false, - }, - } - - for _, tc := range cases { - dockerCfg := &dockercontainer.Config{} - err := modifyContainerConfig(tc.sc, dockerCfg) - if tc.isErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) - } - } -} - -func TestModifyHostConfig(t *testing.T) { - setNetworkHC := &dockercontainer.HostConfig{} - - // When we have Privileged pods, we do not need to use the - // Masked / Readonly paths. - setPrivSC := &runtimeapi.LinuxContainerSecurityContext{} - setPrivSC.Privileged = true - setPrivSC.MaskedPaths = []string{"/hello/world/masked"} - setPrivSC.ReadonlyPaths = []string{"/hello/world/readonly"} - setPrivHC := &dockercontainer.HostConfig{ - Privileged: true, - } - - unsetPrivSC := &runtimeapi.LinuxContainerSecurityContext{} - unsetPrivSC.Privileged = false - unsetPrivSC.MaskedPaths = []string{"/hello/world/masked"} - unsetPrivSC.ReadonlyPaths = []string{"/hello/world/readonly"} - unsetPrivHC := &dockercontainer.HostConfig{ - Privileged: false, - MaskedPaths: []string{"/hello/world/masked"}, - ReadonlyPaths: []string{"/hello/world/readonly"}, - } - - setCapsHC := &dockercontainer.HostConfig{ - CapAdd: []string{"addCapA", "addCapB"}, - CapDrop: []string{"dropCapA", "dropCapB"}, - } - setSELinuxHC := &dockercontainer.HostConfig{ - SecurityOpt: []string{ - fmt.Sprintf("%s:%s", selinuxLabelUser('='), "user"), - fmt.Sprintf("%s:%s", selinuxLabelRole('='), "role"), - fmt.Sprintf("%s:%s", selinuxLabelType('='), "type"), - fmt.Sprintf("%s:%s", selinuxLabelLevel('='), "level"), - }, - } - - cases := []struct { - name string - sc *runtimeapi.LinuxContainerSecurityContext - expected *dockercontainer.HostConfig - }{ - { - name: "fully set container.SecurityContext", - sc: fullValidSecurityContext(), - expected: fullValidHostConfig(), - }, - { - name: "empty container.SecurityContext", - sc: &runtimeapi.LinuxContainerSecurityContext{}, - expected: setNetworkHC, - }, - { - name: "container.SecurityContext.Privileged", - sc: setPrivSC, - expected: setPrivHC, - }, - { - name: "container.SecurityContext.NoPrivileges", - sc: unsetPrivSC, - expected: unsetPrivHC, - }, - { - name: "container.SecurityContext.Capabilities", - sc: &runtimeapi.LinuxContainerSecurityContext{ - Capabilities: inputCapabilities(), - }, - expected: setCapsHC, - }, - { - name: "container.SecurityContext.SELinuxOptions", - sc: &runtimeapi.LinuxContainerSecurityContext{ - SelinuxOptions: inputSELinuxOptions(), - }, - expected: setSELinuxHC, - }, - } - - for _, tc := range cases { - dockerCfg := &dockercontainer.HostConfig{} - modifyHostConfig(tc.sc, dockerCfg, '=') - assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) - } -} - -func TestModifyHostConfigWithGroups(t *testing.T) { - supplementalGroupsSC := &runtimeapi.LinuxContainerSecurityContext{} - supplementalGroupsSC.SupplementalGroups = []int64{2222} - supplementalGroupHC := &dockercontainer.HostConfig{} - supplementalGroupHC.GroupAdd = []string{"2222"} - - testCases := []struct { - name string - securityContext *runtimeapi.LinuxContainerSecurityContext - expected *dockercontainer.HostConfig - }{ - { - name: "nil", - securityContext: nil, - expected: &dockercontainer.HostConfig{}, - }, - { - name: "SupplementalGroup", - securityContext: supplementalGroupsSC, - expected: supplementalGroupHC, - }, - } - - for _, tc := range testCases { - dockerCfg := &dockercontainer.HostConfig{} - modifyHostConfig(tc.securityContext, dockerCfg, '=') - assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) - } -} - -func TestModifyHostConfigAndNamespaceOptionsForContainer(t *testing.T) { - priv := true - sandboxID := "sandbox" - sandboxNSMode := fmt.Sprintf("container:%v", sandboxID) - setPrivSC := &runtimeapi.LinuxContainerSecurityContext{} - setPrivSC.Privileged = priv - setPrivHC := &dockercontainer.HostConfig{ - Privileged: true, - IpcMode: dockercontainer.IpcMode(sandboxNSMode), - NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), - PidMode: dockercontainer.PidMode(sandboxNSMode), - } - setCapsHC := &dockercontainer.HostConfig{ - CapAdd: []string{"addCapA", "addCapB"}, - CapDrop: []string{"dropCapA", "dropCapB"}, - IpcMode: dockercontainer.IpcMode(sandboxNSMode), - NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), - PidMode: dockercontainer.PidMode(sandboxNSMode), - } - setSELinuxHC := &dockercontainer.HostConfig{ - SecurityOpt: []string{ - fmt.Sprintf("%s:%s", selinuxLabelUser('='), "user"), - fmt.Sprintf("%s:%s", selinuxLabelRole('='), "role"), - fmt.Sprintf("%s:%s", selinuxLabelType('='), "type"), - fmt.Sprintf("%s:%s", selinuxLabelLevel('='), "level"), - }, - IpcMode: dockercontainer.IpcMode(sandboxNSMode), - NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), - PidMode: dockercontainer.PidMode(sandboxNSMode), - } - - cases := []struct { - name string - sc *runtimeapi.LinuxContainerSecurityContext - expected *dockercontainer.HostConfig - }{ - { - name: "container.SecurityContext.Privileged", - sc: setPrivSC, - expected: setPrivHC, - }, - { - name: "container.SecurityContext.Capabilities", - sc: &runtimeapi.LinuxContainerSecurityContext{ - Capabilities: inputCapabilities(), - }, - expected: setCapsHC, - }, - { - name: "container.SecurityContext.SELinuxOptions", - sc: &runtimeapi.LinuxContainerSecurityContext{ - SelinuxOptions: inputSELinuxOptions(), - }, - expected: setSELinuxHC, - }, - } - - for _, tc := range cases { - dockerCfg := &dockercontainer.HostConfig{} - modifyHostConfig(tc.sc, dockerCfg, '=') - modifyContainerNamespaceOptions(tc.sc.GetNamespaceOptions(), sandboxID, dockerCfg) - assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) - } -} - -func TestModifySandboxNamespaceOptions(t *testing.T) { - cases := []struct { - name string - nsOpt *runtimeapi.NamespaceOption - expected *dockercontainer.HostConfig - }{ - { - name: "Host Network NamespaceOption", - nsOpt: &runtimeapi.NamespaceOption{ - Network: runtimeapi.NamespaceMode_NODE, - }, - expected: &dockercontainer.HostConfig{ - NetworkMode: namespaceModeHost, - }, - }, - { - name: "Host IPC NamespaceOption", - nsOpt: &runtimeapi.NamespaceOption{ - Ipc: runtimeapi.NamespaceMode_NODE, - }, - expected: &dockercontainer.HostConfig{ - IpcMode: namespaceModeHost, - NetworkMode: "default", - }, - }, - { - name: "Host PID NamespaceOption", - nsOpt: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_NODE, - }, - expected: &dockercontainer.HostConfig{ - PidMode: namespaceModeHost, - NetworkMode: "default", - }, - }, - { - name: "Pod PID NamespaceOption (for sandbox is same as container ns option)", - nsOpt: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_POD, - }, - expected: &dockercontainer.HostConfig{ - PidMode: "", - NetworkMode: "default", - }, - }, - { - name: "Target PID NamespaceOption (invalid for sandbox)", - nsOpt: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_TARGET, - TargetId: "same-container", - }, - expected: &dockercontainer.HostConfig{ - PidMode: "", - NetworkMode: "default", - }, - }, - } - for _, tc := range cases { - dockerCfg := &dockercontainer.HostConfig{} - modifySandboxNamespaceOptions(tc.nsOpt, dockerCfg, nil) - assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) - } -} - -func TestModifyContainerNamespaceOptions(t *testing.T) { - sandboxID := "sandbox" - sandboxNSMode := fmt.Sprintf("container:%v", sandboxID) - cases := []struct { - name string - nsOpt *runtimeapi.NamespaceOption - expected *dockercontainer.HostConfig - }{ - { - name: "Host Network NamespaceOption", - nsOpt: &runtimeapi.NamespaceOption{ - Network: runtimeapi.NamespaceMode_NODE, - }, - expected: &dockercontainer.HostConfig{ - NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), - IpcMode: dockercontainer.IpcMode(sandboxNSMode), - UTSMode: namespaceModeHost, - PidMode: dockercontainer.PidMode(sandboxNSMode), - }, - }, - { - name: "Host IPC NamespaceOption", - nsOpt: &runtimeapi.NamespaceOption{ - Ipc: runtimeapi.NamespaceMode_NODE, - }, - expected: &dockercontainer.HostConfig{ - NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), - IpcMode: dockercontainer.IpcMode(sandboxNSMode), - PidMode: dockercontainer.PidMode(sandboxNSMode), - }, - }, - { - name: "Host PID NamespaceOption", - nsOpt: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_NODE, - }, - expected: &dockercontainer.HostConfig{ - NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), - IpcMode: dockercontainer.IpcMode(sandboxNSMode), - PidMode: namespaceModeHost, - }, - }, - { - name: "Pod PID NamespaceOption", - nsOpt: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_POD, - }, - expected: &dockercontainer.HostConfig{ - NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), - IpcMode: dockercontainer.IpcMode(sandboxNSMode), - PidMode: dockercontainer.PidMode(sandboxNSMode), - }, - }, - { - name: "Target PID NamespaceOption", - nsOpt: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_TARGET, - TargetId: "some-container", - }, - expected: &dockercontainer.HostConfig{ - NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), - IpcMode: dockercontainer.IpcMode(sandboxNSMode), - PidMode: dockercontainer.PidMode("container:some-container"), - }, - }, - } - for _, tc := range cases { - dockerCfg := &dockercontainer.HostConfig{} - modifyContainerNamespaceOptions(tc.nsOpt, sandboxID, dockerCfg) - assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) - } -} - -func fullValidSecurityContext() *runtimeapi.LinuxContainerSecurityContext { - return &runtimeapi.LinuxContainerSecurityContext{ - Privileged: true, - Capabilities: inputCapabilities(), - SelinuxOptions: inputSELinuxOptions(), - } -} - -func inputCapabilities() *runtimeapi.Capability { - return &runtimeapi.Capability{ - AddCapabilities: []string{"addCapA", "addCapB"}, - DropCapabilities: []string{"dropCapA", "dropCapB"}, - } -} - -func inputSELinuxOptions() *runtimeapi.SELinuxOption { - user := "user" - role := "role" - stype := "type" - level := "level" - - return &runtimeapi.SELinuxOption{ - User: user, - Role: role, - Type: stype, - Level: level, - } -} - -func fullValidHostConfig() *dockercontainer.HostConfig { - return &dockercontainer.HostConfig{ - Privileged: true, - CapAdd: []string{"addCapA", "addCapB"}, - CapDrop: []string{"dropCapA", "dropCapB"}, - SecurityOpt: []string{ - fmt.Sprintf("%s:%s", selinuxLabelUser('='), "user"), - fmt.Sprintf("%s:%s", selinuxLabelRole('='), "role"), - fmt.Sprintf("%s:%s", selinuxLabelType('='), "type"), - fmt.Sprintf("%s:%s", selinuxLabelLevel('='), "level"), - }, - } -} diff --git a/pkg/kubelet/dockershim/selinux_util.go b/pkg/kubelet/dockershim/selinux_util.go deleted file mode 100644 index 4d299a7f934..00000000000 --- a/pkg/kubelet/dockershim/selinux_util.go +++ /dev/null @@ -1,89 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "fmt" - - runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" -) - -// selinuxLabelUser returns the fragment of a Docker security opt that -// describes the SELinux user. Note that strictly speaking this is not -// actually the name of the security opt, but a fragment of the whole key- -// value pair necessary to set the opt. -func selinuxLabelUser(separator rune) string { - return fmt.Sprintf("label%cuser", separator) -} - -// selinuxLabelRole returns the fragment of a Docker security opt that -// describes the SELinux role. Note that strictly speaking this is not -// actually the name of the security opt, but a fragment of the whole key- -// value pair necessary to set the opt. -func selinuxLabelRole(separator rune) string { - return fmt.Sprintf("label%crole", separator) -} - -// selinuxLabelType returns the fragment of a Docker security opt that -// describes the SELinux type. Note that strictly speaking this is not -// actually the name of the security opt, but a fragment of the whole key- -// value pair necessary to set the opt. -func selinuxLabelType(separator rune) string { - return fmt.Sprintf("label%ctype", separator) -} - -// selinuxLabelLevel returns the fragment of a Docker security opt that -// describes the SELinux level. Note that strictly speaking this is not -// actually the name of the security opt, but a fragment of the whole key- -// value pair necessary to set the opt. -func selinuxLabelLevel(separator rune) string { - return fmt.Sprintf("label%clevel", separator) -} - -// addSELinuxOptions adds SELinux options to config using the given -// separator. -func addSELinuxOptions(config []string, selinuxOpts *runtimeapi.SELinuxOption, separator rune) []string { - // Note, strictly speaking, we are actually mutating the values of these - // keys, rather than formatting name and value into a string. Docker re- - // uses the same option name multiple times (it's just 'label') with - // different values which are themselves key-value pairs. For example, - // the SELinux type is represented by the security opt: - // - // labeltype: - // - // In Docker API versions before 1.23, the separator was the `:` rune; in - // API version 1.23 it changed to the `=` rune. - config = modifySecurityOption(config, selinuxLabelUser(separator), selinuxOpts.User) - config = modifySecurityOption(config, selinuxLabelRole(separator), selinuxOpts.Role) - config = modifySecurityOption(config, selinuxLabelType(separator), selinuxOpts.Type) - config = modifySecurityOption(config, selinuxLabelLevel(separator), selinuxOpts.Level) - - return config -} - -// modifySecurityOption adds the security option of name to the config array -// with value in the form of name:value. -func modifySecurityOption(config []string, name, value string) []string { - if len(value) > 0 { - config = append(config, fmt.Sprintf("%s:%s", name, value)) - } - - return config -} diff --git a/pkg/kubelet/dockershim/selinux_util_test.go b/pkg/kubelet/dockershim/selinux_util_test.go deleted file mode 100644 index d1e47dbcd14..00000000000 --- a/pkg/kubelet/dockershim/selinux_util_test.go +++ /dev/null @@ -1,57 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dockershim - -import ( - "reflect" - "testing" -) - -func TestModifySecurityOptions(t *testing.T) { - testCases := []struct { - name string - config []string - optName string - optVal string - expected []string - }{ - { - name: "Empty val", - config: []string{"a:b", "c:d"}, - optName: "optA", - optVal: "", - expected: []string{"a:b", "c:d"}, - }, - { - name: "Valid", - config: []string{"a:b", "c:d"}, - optName: "e", - optVal: "f", - expected: []string{"a:b", "c:d", "e:f"}, - }, - } - - for _, tc := range testCases { - actual := modifySecurityOption(tc.config, tc.optName, tc.optVal) - if !reflect.DeepEqual(tc.expected, actual) { - t.Errorf("Failed to apply options correctly for tc: %s. Expected: %v but got %v", tc.name, tc.expected, actual) - } - } -} diff --git a/pkg/kubelet/kubelet_dockershim.go b/pkg/kubelet/kubelet_dockershim.go deleted file mode 100644 index edc486949e8..00000000000 --- a/pkg/kubelet/kubelet_dockershim.go +++ /dev/null @@ -1,80 +0,0 @@ -//go:build !dockerless -// +build !dockerless - -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package kubelet - -import ( - "k8s.io/klog/v2" - - kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config" - "k8s.io/kubernetes/pkg/kubelet/config" - "k8s.io/kubernetes/pkg/kubelet/dockershim" - dockerremote "k8s.io/kubernetes/pkg/kubelet/dockershim/remote" -) - -func runDockershim(kubeCfg *kubeletconfiginternal.KubeletConfiguration, - kubeDeps *Dependencies, - crOptions *config.ContainerRuntimeOptions, - runtimeCgroups string, - remoteRuntimeEndpoint string, - remoteImageEndpoint string, - nonMasqueradeCIDR string) error { - pluginSettings := dockershim.NetworkPluginSettings{ - HairpinMode: kubeletconfiginternal.HairpinMode(kubeCfg.HairpinMode), - NonMasqueradeCIDR: nonMasqueradeCIDR, - PluginName: crOptions.NetworkPluginName, - PluginConfDir: crOptions.CNIConfDir, - PluginBinDirString: crOptions.CNIBinDir, - PluginCacheDir: crOptions.CNICacheDir, - MTU: int(crOptions.NetworkPluginMTU), - } - - // Create and start the CRI shim running as a grpc server. - streamingConfig := getStreamingConfig(kubeCfg, kubeDeps, crOptions) - dockerClientConfig := &dockershim.ClientConfig{ - DockerEndpoint: kubeDeps.DockerOptions.DockerEndpoint, - RuntimeRequestTimeout: kubeDeps.DockerOptions.RuntimeRequestTimeout, - ImagePullProgressDeadline: kubeDeps.DockerOptions.ImagePullProgressDeadline, - } - ds, err := dockershim.NewDockerService(dockerClientConfig, crOptions.PodSandboxImage, streamingConfig, - &pluginSettings, runtimeCgroups, kubeCfg.CgroupDriver, crOptions.DockershimRootDirectory) - if err != nil { - return err - } - - // The unix socket for kubelet <-> dockershim communication, dockershim start before runtime service init. - klog.V(5).InfoS("Using remote runtime endpoint and image endpoint", "runtimeEndpoint", remoteRuntimeEndpoint, "imageEndpoint", remoteImageEndpoint) - klog.V(2).InfoS("Starting the GRPC server for the docker CRI shim.") - - dockerServer := dockerremote.NewDockerServer(remoteRuntimeEndpoint, ds) - if err := dockerServer.Start(); err != nil { - return err - } - - // Create dockerLegacyService when the logging driver is not supported. - supported, err := ds.IsCRISupportedLogDriver() - if err != nil { - return err - } - if !supported { - kubeDeps.dockerLegacyService = ds - } - - return nil -} From bc78dff42ec6be929648e91f3ef2dd6dae5169fb Mon Sep 17 00:00:00 2001 From: Davanum Srinivas Date: Tue, 7 Dec 2021 14:48:57 -0500 Subject: [PATCH 2/3] update files to drop dockershim Signed-off-by: Davanum Srinivas --- build/dependencies.yaml | 2 -- cmd/kubelet/app/options/globalflags_linux.go | 11 -------- go.mod | 5 ---- go.sum | 3 --- pkg/kubelet/kubelet.go | 26 +------------------ .../legacy-cloud-providers/aws/aws_fakes.go | 1 + test/e2e/framework/.import-restrictions | 10 ------- 7 files changed, 2 insertions(+), 56 deletions(-) diff --git a/build/dependencies.yaml b/build/dependencies.yaml index ff296e255b9..b0b1b5a6d41 100644 --- a/build/dependencies.yaml +++ b/build/dependencies.yaml @@ -172,8 +172,6 @@ dependencies: match: defaultPodSandboxImageVersion\s+= - path: hack/testdata/pod-with-precision.json match: k8s.gcr.io\/pause:\d+\.\d+ - - path: pkg/kubelet/dockershim/docker_sandbox.go - match: k8s.gcr.io\/pause:\d+\.\d+ - path: staging/src/k8s.io/kubectl/testdata/set/multi-resource-yaml.yaml match: k8s.gcr.io\/pause:\d+\.\d+ - path: staging/src/k8s.io/kubectl/testdata/set/namespaced-resource.yaml diff --git a/cmd/kubelet/app/options/globalflags_linux.go b/cmd/kubelet/app/options/globalflags_linux.go index ad3b68628f6..e75e65ec37c 100644 --- a/cmd/kubelet/app/options/globalflags_linux.go +++ b/cmd/kubelet/app/options/globalflags_linux.go @@ -28,7 +28,6 @@ import ( // ensure libs have a chance to globally register their flags _ "github.com/google/cadvisor/container/common" _ "github.com/google/cadvisor/container/containerd" - _ "github.com/google/cadvisor/container/docker" _ "github.com/google/cadvisor/container/raw" _ "github.com/google/cadvisor/machine" _ "github.com/google/cadvisor/manager" @@ -41,9 +40,6 @@ func addCadvisorFlags(fs *pflag.FlagSet) { global := flag.CommandLine local := pflag.NewFlagSet(os.Args[0], pflag.ExitOnError) - // These flags were also implicit from cadvisor, but are actually used by something in the core repo: - // TODO(mtaufen): This one is stil used by our salt, but for heaven's sake it's even deprecated in cadvisor - register(global, local, "docker_root") // e2e node tests rely on this register(global, local, "housekeeping_interval") @@ -54,13 +50,6 @@ func addCadvisorFlags(fs *pflag.FlagSet) { registerDeprecated(global, local, "boot_id_file", deprecated) registerDeprecated(global, local, "container_hints", deprecated) registerDeprecated(global, local, "containerd", deprecated) - registerDeprecated(global, local, "docker", deprecated) - registerDeprecated(global, local, "docker_env_metadata_whitelist", deprecated) - registerDeprecated(global, local, "docker_only", deprecated) - registerDeprecated(global, local, "docker-tls", deprecated) - registerDeprecated(global, local, "docker-tls-ca", deprecated) - registerDeprecated(global, local, "docker-tls-cert", deprecated) - registerDeprecated(global, local, "docker-tls-key", deprecated) registerDeprecated(global, local, "enable_load_reader", deprecated) registerDeprecated(global, local, "event_storage_age_limit", deprecated) registerDeprecated(global, local, "event_storage_event_limit", deprecated) diff --git a/go.mod b/go.mod index a17878d68d0..7dccd35bb6b 100644 --- a/go.mod +++ b/go.mod @@ -25,15 +25,12 @@ require ( github.com/boltdb/bolt v1.3.1 // indirect github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 github.com/container-storage-interface/spec v1.5.0 - github.com/containernetworking/cni v0.8.1 github.com/coredns/corefile-migration v1.0.14 github.com/coreos/go-oidc v2.1.0+incompatible github.com/coreos/go-systemd/v22 v22.3.2 github.com/cpuguy83/go-md2man/v2 v2.0.0 github.com/davecgh/go-spew v1.1.1 github.com/docker/distribution v2.7.1+incompatible - github.com/docker/docker v20.10.7+incompatible - github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.4.0 github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 github.com/emicklei/go-restful v2.9.5+incompatible @@ -63,7 +60,6 @@ require ( github.com/mvdan/xurls v1.1.0 github.com/onsi/ginkgo v1.14.0 github.com/onsi/gomega v1.10.1 - github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/runc v1.0.2 github.com/opencontainers/selinux v1.8.2 github.com/pkg/errors v0.9.1 @@ -209,7 +205,6 @@ replace ( github.com/containerd/go-runc => github.com/containerd/go-runc v1.0.0 github.com/containerd/ttrpc => github.com/containerd/ttrpc v1.0.2 github.com/containerd/typeurl => github.com/containerd/typeurl v1.0.2 - github.com/containernetworking/cni => github.com/containernetworking/cni v0.8.1 github.com/coredns/caddy => github.com/coredns/caddy v1.1.0 github.com/coredns/corefile-migration => github.com/coredns/corefile-migration v1.0.14 github.com/coreos/go-oidc => github.com/coreos/go-oidc v2.1.0+incompatible diff --git a/go.sum b/go.sum index b458fb06802..9121b2f4ac8 100644 --- a/go.sum +++ b/go.sum @@ -116,8 +116,6 @@ github.com/containerd/ttrpc v1.0.2 h1:2/O3oTZN36q2xRolk0a2WWGgh7/Vf/liElg5hFYLX9 github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containernetworking/cni v0.8.1 h1:7zpDnQ3T3s4ucOuJ/ZCLrYBxzkg0AELFfII3Epo9TmI= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/coredns/caddy v1.1.0 h1:ezvsPrT/tA/7pYDBZxu0cT0VmWk75AfIaf6GSYCNMf0= github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/corefile-migration v1.0.14 h1:Tz3WZhoj2NdP8drrQH86NgnCng+VrPjNeg2Oe1ALKag= @@ -353,7 +351,6 @@ github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb h1:e+l77LJOEqXTIQih github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0 h1:NKzVxiH7eSk+OQ4M+ZYW1K6h27RUV3MI6NUTsHhU6Z4= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 2013c871a60..0e6f5f946de 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -73,7 +73,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/configmap" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/cri/remote" - "k8s.io/kubernetes/pkg/kubelet/cri/streaming" "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/pkg/kubelet/eviction" "k8s.io/kubernetes/pkg/kubelet/images" @@ -310,18 +309,7 @@ func PreInitRuntimeService(kubeCfg *kubeletconfiginternal.KubeletConfiguration, switch containerRuntime { case kubetypes.DockerContainerRuntime: - klog.InfoS("Using dockershim is deprecated, please consider using a full-fledged CRI implementation") - if err := runDockershim( - kubeCfg, - kubeDeps, - crOptions, - runtimeCgroups, - remoteRuntimeEndpoint, - remoteImageEndpoint, - nonMasqueradeCIDR, - ); err != nil { - return err - } + return fmt.Errorf("using dockershim is not supported, please consider using a full-fledged CRI implementation") case kubetypes.RemoteContainerRuntime: // No-op. break @@ -2440,15 +2428,3 @@ func isSyncPodWorthy(event *pleg.PodLifecycleEvent) bool { // ContainerRemoved doesn't affect pod state return event.Type != pleg.ContainerRemoved } - -// Gets the streaming server configuration to use with in-process CRI shims. -func getStreamingConfig(kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *Dependencies, crOptions *config.ContainerRuntimeOptions) *streaming.Config { - config := &streaming.Config{ - StreamIdleTimeout: kubeCfg.StreamingConnectionIdleTimeout.Duration, - StreamCreationTimeout: streaming.DefaultConfig.StreamCreationTimeout, - SupportedRemoteCommandProtocols: streaming.DefaultConfig.SupportedRemoteCommandProtocols, - SupportedPortForwardProtocols: streaming.DefaultConfig.SupportedPortForwardProtocols, - } - config.Addr = net.JoinHostPort("localhost", "0") - return config -} diff --git a/staging/src/k8s.io/legacy-cloud-providers/aws/aws_fakes.go b/staging/src/k8s.io/legacy-cloud-providers/aws/aws_fakes.go index 06fdc92493b..c970a6aaa02 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/aws/aws_fakes.go +++ b/staging/src/k8s.io/legacy-cloud-providers/aws/aws_fakes.go @@ -30,6 +30,7 @@ import ( "github.com/aws/aws-sdk-go/service/elb" "github.com/aws/aws-sdk-go/service/elbv2" "github.com/aws/aws-sdk-go/service/kms" + _ "github.com/stretchr/testify/mock" "k8s.io/klog/v2" ) diff --git a/test/e2e/framework/.import-restrictions b/test/e2e/framework/.import-restrictions index a60fb9d7908..1353f40df9d 100644 --- a/test/e2e/framework/.import-restrictions +++ b/test/e2e/framework/.import-restrictions @@ -86,16 +86,6 @@ rules: - k8s.io/kubernetes/pkg/kubelet/config - k8s.io/kubernetes/pkg/kubelet/configmap - k8s.io/kubernetes/pkg/kubelet/container - - k8s.io/kubernetes/pkg/kubelet/dockershim - - k8s.io/kubernetes/pkg/kubelet/dockershim/cm - - k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker - - k8s.io/kubernetes/pkg/kubelet/dockershim/metrics - - k8s.io/kubernetes/pkg/kubelet/dockershim/network - - k8s.io/kubernetes/pkg/kubelet/dockershim/network/cni - - k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport - - k8s.io/kubernetes/pkg/kubelet/dockershim/network/kubenet - - k8s.io/kubernetes/pkg/kubelet/dockershim/network/metrics - - k8s.io/kubernetes/pkg/kubelet/dockershim/remote - k8s.io/kubernetes/pkg/kubelet/envvars - k8s.io/kubernetes/pkg/kubelet/eviction - k8s.io/kubernetes/pkg/kubelet/eviction/api From 420145e529bad15895ae8da895f7c3c8a8949276 Mon Sep 17 00:00:00 2001 From: Davanum Srinivas Date: Tue, 7 Dec 2021 14:47:35 -0500 Subject: [PATCH 3/3] drop things from vendor/ directory Signed-off-by: Davanum Srinivas --- .../containerd/containerd/errdefs/errors.go | 93 - .../containerd/containerd/errdefs/grpc.go | 147 - .../containerd/containerd/log/context.go | 60 - .../containerd/platforms/compare.go | 229 - .../containerd/platforms/cpuinfo.go | 122 - .../containerd/platforms/database.go | 114 - .../containerd/platforms/defaults.go | 38 - .../containerd/platforms/defaults_unix.go | 24 - .../containerd/platforms/defaults_windows.go | 31 - .../containerd/platforms/platforms.go | 278 - .../containernetworking/cni/LICENSE | 202 - .../containernetworking/cni/libcni/api.go | 673 - .../containernetworking/cni/libcni/conf.go | 268 - .../cni/pkg/invoke/args.go | 128 - .../cni/pkg/invoke/delegate.go | 80 - .../cni/pkg/invoke/exec.go | 144 - .../cni/pkg/invoke/find.go | 48 - .../cni/pkg/invoke/os_unix.go | 20 - .../cni/pkg/invoke/os_windows.go | 18 - .../cni/pkg/invoke/raw_exec.go | 88 - .../cni/pkg/types/020/types.go | 126 - .../containernetworking/cni/pkg/types/args.go | 112 - .../cni/pkg/types/current/types.go | 276 - .../cni/pkg/types/types.go | 207 - .../cni/pkg/utils/utils.go | 84 - .../cni/pkg/version/conf.go | 37 - .../cni/pkg/version/plugin.go | 144 - .../cni/pkg/version/reconcile.go | 49 - .../cni/pkg/version/version.go | 83 - .../registry/api/errcode/errors.go | 267 - .../registry/api/errcode/handler.go | 40 - .../registry/api/errcode/register.go | 138 - vendor/github.com/docker/docker/AUTHORS | 2175 --- vendor/github.com/docker/docker/LICENSE | 191 - vendor/github.com/docker/docker/NOTICE | 19 - vendor/github.com/docker/docker/api/README.md | 42 - vendor/github.com/docker/docker/api/common.go | 11 - .../docker/docker/api/common_unix.go | 6 - .../docker/docker/api/common_windows.go | 8 - .../docker/docker/api/swagger-gen.yaml | 12 - .../github.com/docker/docker/api/swagger.yaml | 11425 ---------------- .../docker/docker/api/types/auth.go | 22 - .../docker/docker/api/types/blkiodev/blkio.go | 23 - .../docker/docker/api/types/client.go | 419 - .../docker/docker/api/types/configs.go | 66 - .../docker/api/types/container/config.go | 69 - .../api/types/container/container_changes.go | 20 - .../api/types/container/container_create.go | 20 - .../api/types/container/container_top.go | 22 - .../api/types/container/container_update.go | 16 - .../api/types/container/container_wait.go | 28 - .../docker/api/types/container/host_config.go | 447 - .../api/types/container/hostconfig_unix.go | 41 - .../api/types/container/hostconfig_windows.go | 40 - .../api/types/container/waitcondition.go | 22 - .../docker/docker/api/types/error_response.go | 13 - .../docker/api/types/error_response_ext.go | 6 - .../docker/docker/api/types/events/events.go | 54 - .../docker/docker/api/types/filters/parse.go | 324 - .../docker/api/types/graph_driver_data.go | 17 - .../docker/docker/api/types/id_response.go | 13 - .../docker/api/types/image/image_history.go | 36 - .../api/types/image_delete_response_item.go | 15 - .../docker/docker/api/types/image_summary.go | 49 - .../docker/docker/api/types/mount/mount.go | 131 - .../docker/api/types/network/network.go | 126 - .../docker/docker/api/types/plugin.go | 203 - .../docker/docker/api/types/plugin_device.go | 25 - .../docker/docker/api/types/plugin_env.go | 25 - .../docker/api/types/plugin_interface_type.go | 21 - .../docker/docker/api/types/plugin_mount.go | 37 - .../docker/api/types/plugin_responses.go | 71 - .../docker/docker/api/types/port.go | 23 - .../docker/api/types/registry/authenticate.go | 21 - .../docker/api/types/registry/registry.go | 119 - .../api/types/service_update_response.go | 12 - .../docker/docker/api/types/stats.go | 181 - .../docker/api/types/strslice/strslice.go | 30 - .../docker/docker/api/types/swarm/common.go | 40 - .../docker/docker/api/types/swarm/config.go | 40 - .../docker/api/types/swarm/container.go | 80 - .../docker/docker/api/types/swarm/network.go | 121 - .../docker/docker/api/types/swarm/node.go | 115 - .../docker/docker/api/types/swarm/runtime.go | 27 - .../docker/api/types/swarm/runtime/gen.go | 3 - .../api/types/swarm/runtime/plugin.pb.go | 754 - .../api/types/swarm/runtime/plugin.proto | 21 - .../docker/docker/api/types/swarm/secret.go | 36 - .../docker/docker/api/types/swarm/service.go | 202 - .../docker/docker/api/types/swarm/swarm.go | 227 - .../docker/docker/api/types/swarm/task.go | 206 - .../docker/api/types/time/duration_convert.go | 12 - .../docker/docker/api/types/time/timestamp.go | 129 - .../docker/docker/api/types/types.go | 635 - .../docker/api/types/versions/README.md | 14 - .../docker/api/types/versions/compare.go | 62 - .../docker/docker/api/types/volume.go | 72 - .../docker/api/types/volume/volume_create.go | 31 - .../docker/api/types/volume/volume_list.go | 23 - .../github.com/docker/docker/client/README.md | 35 - .../docker/docker/client/build_cancel.go | 16 - .../docker/docker/client/build_prune.go | 45 - .../docker/docker/client/checkpoint_create.go | 14 - .../docker/docker/client/checkpoint_delete.go | 20 - .../docker/docker/client/checkpoint_list.go | 28 - .../github.com/docker/docker/client/client.go | 310 - .../docker/docker/client/client_deprecated.go | 23 - .../docker/docker/client/client_unix.go | 9 - .../docker/docker/client/client_windows.go | 7 - .../docker/docker/client/config_create.go | 25 - .../docker/docker/client/config_inspect.go | 36 - .../docker/docker/client/config_list.go | 38 - .../docker/docker/client/config_remove.go | 13 - .../docker/docker/client/config_update.go | 21 - .../docker/docker/client/container_attach.go | 57 - .../docker/docker/client/container_commit.go | 55 - .../docker/docker/client/container_copy.go | 103 - .../docker/docker/client/container_create.go | 63 - .../docker/docker/client/container_diff.go | 23 - .../docker/docker/client/container_exec.go | 54 - .../docker/docker/client/container_export.go | 19 - .../docker/docker/client/container_inspect.go | 53 - .../docker/docker/client/container_kill.go | 16 - .../docker/docker/client/container_list.go | 57 - .../docker/docker/client/container_logs.go | 80 - .../docker/docker/client/container_pause.go | 10 - .../docker/docker/client/container_prune.go | 36 - .../docker/docker/client/container_remove.go | 27 - .../docker/docker/client/container_rename.go | 15 - .../docker/docker/client/container_resize.go | 29 - .../docker/docker/client/container_restart.go | 22 - .../docker/docker/client/container_start.go | 23 - .../docker/docker/client/container_stats.go | 42 - .../docker/docker/client/container_stop.go | 26 - .../docker/docker/client/container_top.go | 28 - .../docker/docker/client/container_unpause.go | 10 - .../docker/docker/client/container_update.go | 21 - .../docker/docker/client/container_wait.go | 83 - .../docker/docker/client/disk_usage.go | 26 - .../docker/client/distribution_inspect.go | 38 - .../github.com/docker/docker/client/errors.go | 138 - .../github.com/docker/docker/client/events.go | 102 - .../github.com/docker/docker/client/hijack.go | 145 - .../docker/docker/client/image_build.go | 146 - .../docker/docker/client/image_create.go | 37 - .../docker/docker/client/image_history.go | 22 - .../docker/docker/client/image_import.go | 40 - .../docker/docker/client/image_inspect.go | 32 - .../docker/docker/client/image_list.go | 46 - .../docker/docker/client/image_load.go | 29 - .../docker/docker/client/image_prune.go | 36 - .../docker/docker/client/image_pull.go | 64 - .../docker/docker/client/image_push.go | 54 - .../docker/docker/client/image_remove.go | 31 - .../docker/docker/client/image_save.go | 21 - .../docker/docker/client/image_search.go | 51 - .../docker/docker/client/image_tag.go | 37 - .../github.com/docker/docker/client/info.go | 26 - .../docker/docker/client/interface.go | 201 - .../docker/client/interface_experimental.go | 18 - .../docker/docker/client/interface_stable.go | 10 - .../github.com/docker/docker/client/login.go | 25 - .../docker/docker/client/network_connect.go | 19 - .../docker/docker/client/network_create.go | 25 - .../docker/client/network_disconnect.go | 15 - .../docker/docker/client/network_inspect.go | 49 - .../docker/docker/client/network_list.go | 32 - .../docker/docker/client/network_prune.go | 36 - .../docker/docker/client/network_remove.go | 10 - .../docker/docker/client/node_inspect.go | 32 - .../docker/docker/client/node_list.go | 36 - .../docker/docker/client/node_remove.go | 20 - .../docker/docker/client/node_update.go | 18 - .../docker/docker/client/options.go | 172 - .../github.com/docker/docker/client/ping.go | 66 - .../docker/docker/client/plugin_create.go | 23 - .../docker/docker/client/plugin_disable.go | 19 - .../docker/docker/client/plugin_enable.go | 19 - .../docker/docker/client/plugin_inspect.go | 31 - .../docker/docker/client/plugin_install.go | 113 - .../docker/docker/client/plugin_list.go | 33 - .../docker/docker/client/plugin_push.go | 16 - .../docker/docker/client/plugin_remove.go | 20 - .../docker/docker/client/plugin_set.go | 12 - .../docker/docker/client/plugin_upgrade.go | 39 - .../docker/docker/client/request.go | 269 - .../docker/docker/client/secret_create.go | 25 - .../docker/docker/client/secret_inspect.go | 36 - .../docker/docker/client/secret_list.go | 38 - .../docker/docker/client/secret_remove.go | 13 - .../docker/docker/client/secret_update.go | 21 - .../docker/docker/client/service_create.go | 178 - .../docker/docker/client/service_inspect.go | 37 - .../docker/docker/client/service_list.go | 39 - .../docker/docker/client/service_logs.go | 52 - .../docker/docker/client/service_remove.go | 10 - .../docker/docker/client/service_update.go | 75 - .../docker/client/swarm_get_unlock_key.go | 21 - .../docker/docker/client/swarm_init.go | 21 - .../docker/docker/client/swarm_inspect.go | 21 - .../docker/docker/client/swarm_join.go | 14 - .../docker/docker/client/swarm_leave.go | 17 - .../docker/docker/client/swarm_unlock.go | 14 - .../docker/docker/client/swarm_update.go | 22 - .../docker/docker/client/task_inspect.go | 32 - .../docker/docker/client/task_list.go | 35 - .../docker/docker/client/task_logs.go | 51 - .../docker/docker/client/transport.go | 17 - .../github.com/docker/docker/client/utils.go | 34 - .../docker/docker/client/version.go | 21 - .../docker/docker/client/volume_create.go | 21 - .../docker/docker/client/volume_inspect.go | 38 - .../docker/docker/client/volume_list.go | 33 - .../docker/docker/client/volume_prune.go | 36 - .../docker/docker/client/volume_remove.go | 21 - .../github.com/docker/docker/errdefs/defs.go | 69 - .../github.com/docker/docker/errdefs/doc.go | 8 - .../docker/docker/errdefs/helpers.go | 279 - .../docker/docker/errdefs/http_helpers.go | 191 - vendor/github.com/docker/docker/errdefs/is.go | 107 - .../docker/pkg/jsonmessage/jsonmessage.go | 283 - .../docker/docker/pkg/stdcopy/stdcopy.go | 190 - .../github.com/docker/go-connections/LICENSE | 191 - .../docker/go-connections/nat/nat.go | 242 - .../docker/go-connections/nat/parse.go | 57 - .../docker/go-connections/nat/sort.go | 96 - .../docker/go-connections/sockets/README.md | 0 .../go-connections/sockets/inmem_socket.go | 81 - .../docker/go-connections/sockets/proxy.go | 51 - .../docker/go-connections/sockets/sockets.go | 38 - .../go-connections/sockets/sockets_unix.go | 35 - .../go-connections/sockets/sockets_windows.go | 27 - .../go-connections/sockets/tcp_socket.go | 22 - .../go-connections/sockets/unix_socket.go | 32 - .../go-connections/tlsconfig/certpool_go17.go | 18 - .../tlsconfig/certpool_other.go | 13 - .../docker/go-connections/tlsconfig/config.go | 254 - .../tlsconfig/config_client_ciphers.go | 17 - .../tlsconfig/config_legacy_client_ciphers.go | 15 - .../cadvisor/container/docker/client.go | 61 - .../cadvisor/container/docker/docker.go | 200 - .../cadvisor/container/docker/factory.go | 396 - .../cadvisor/container/docker/handler.go | 517 - .../container/docker/install/install.go | 30 - .../cadvisor/container/docker/plugin.go | 78 - .../cadvisor/container/docker/utils/docker.go | 77 - .../github.com/google/cadvisor/zfs/watcher.go | 113 - vendor/github.com/morikuni/aec/LICENSE | 21 - vendor/github.com/morikuni/aec/README.md | 178 - vendor/github.com/morikuni/aec/aec.go | 137 - vendor/github.com/morikuni/aec/ansi.go | 59 - vendor/github.com/morikuni/aec/builder.go | 388 - vendor/github.com/morikuni/aec/sample.gif | Bin 12548 -> 0 bytes vendor/github.com/morikuni/aec/sgr.go | 202 - .../opencontainers/image-spec/LICENSE | 191 - .../image-spec/specs-go/v1/annotations.go | 56 - .../image-spec/specs-go/v1/config.go | 103 - .../image-spec/specs-go/v1/descriptor.go | 64 - .../image-spec/specs-go/v1/index.go | 29 - .../image-spec/specs-go/v1/layout.go | 28 - .../image-spec/specs-go/v1/manifest.go | 32 - .../image-spec/specs-go/v1/mediatype.go | 48 - .../image-spec/specs-go/version.go | 32 - .../image-spec/specs-go/versioned.go | 23 - .../golang.org/x/net/internal/socks/client.go | 168 - .../golang.org/x/net/internal/socks/socks.go | 317 - vendor/golang.org/x/net/proxy/dial.go | 54 - vendor/golang.org/x/net/proxy/direct.go | 31 - vendor/golang.org/x/net/proxy/per_host.go | 155 - vendor/golang.org/x/net/proxy/proxy.go | 149 - vendor/golang.org/x/net/proxy/socks5.go | 42 - vendor/k8s.io/utils/net/ebtables/ebtables.go | 222 - vendor/modules.txt | 54 - 273 files changed, 35569 deletions(-) delete mode 100644 vendor/github.com/containerd/containerd/errdefs/errors.go delete mode 100644 vendor/github.com/containerd/containerd/errdefs/grpc.go delete mode 100644 vendor/github.com/containerd/containerd/log/context.go delete mode 100644 vendor/github.com/containerd/containerd/platforms/compare.go delete mode 100644 vendor/github.com/containerd/containerd/platforms/cpuinfo.go delete mode 100644 vendor/github.com/containerd/containerd/platforms/database.go delete mode 100644 vendor/github.com/containerd/containerd/platforms/defaults.go delete mode 100644 vendor/github.com/containerd/containerd/platforms/defaults_unix.go delete mode 100644 vendor/github.com/containerd/containerd/platforms/defaults_windows.go delete mode 100644 vendor/github.com/containerd/containerd/platforms/platforms.go delete mode 100644 vendor/github.com/containernetworking/cni/LICENSE delete mode 100644 vendor/github.com/containernetworking/cni/libcni/api.go delete mode 100644 vendor/github.com/containernetworking/cni/libcni/conf.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/args.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/exec.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/find.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/types/020/types.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/types/args.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/types/current/types.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/types/types.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/utils/utils.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/version/conf.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/version/plugin.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/version/reconcile.go delete mode 100644 vendor/github.com/containernetworking/cni/pkg/version/version.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/errcode/errors.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/errcode/handler.go delete mode 100644 vendor/github.com/docker/distribution/registry/api/errcode/register.go delete mode 100644 vendor/github.com/docker/docker/AUTHORS delete mode 100644 vendor/github.com/docker/docker/LICENSE delete mode 100644 vendor/github.com/docker/docker/NOTICE delete mode 100644 vendor/github.com/docker/docker/api/README.md delete mode 100644 vendor/github.com/docker/docker/api/common.go delete mode 100644 vendor/github.com/docker/docker/api/common_unix.go delete mode 100644 vendor/github.com/docker/docker/api/common_windows.go delete mode 100644 vendor/github.com/docker/docker/api/swagger-gen.yaml delete mode 100644 vendor/github.com/docker/docker/api/swagger.yaml delete mode 100644 vendor/github.com/docker/docker/api/types/auth.go delete mode 100644 vendor/github.com/docker/docker/api/types/blkiodev/blkio.go delete mode 100644 vendor/github.com/docker/docker/api/types/client.go delete mode 100644 vendor/github.com/docker/docker/api/types/configs.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/config.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/container_changes.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/container_create.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/container_top.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/container_update.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/container_wait.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/host_config.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/waitcondition.go delete mode 100644 vendor/github.com/docker/docker/api/types/error_response.go delete mode 100644 vendor/github.com/docker/docker/api/types/error_response_ext.go delete mode 100644 vendor/github.com/docker/docker/api/types/events/events.go delete mode 100644 vendor/github.com/docker/docker/api/types/filters/parse.go delete mode 100644 vendor/github.com/docker/docker/api/types/graph_driver_data.go delete mode 100644 vendor/github.com/docker/docker/api/types/id_response.go delete mode 100644 vendor/github.com/docker/docker/api/types/image/image_history.go delete mode 100644 vendor/github.com/docker/docker/api/types/image_delete_response_item.go delete mode 100644 vendor/github.com/docker/docker/api/types/image_summary.go delete mode 100644 vendor/github.com/docker/docker/api/types/mount/mount.go delete mode 100644 vendor/github.com/docker/docker/api/types/network/network.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_device.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_env.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_interface_type.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_mount.go delete mode 100644 vendor/github.com/docker/docker/api/types/plugin_responses.go delete mode 100644 vendor/github.com/docker/docker/api/types/port.go delete mode 100644 vendor/github.com/docker/docker/api/types/registry/authenticate.go delete mode 100644 vendor/github.com/docker/docker/api/types/registry/registry.go delete mode 100644 vendor/github.com/docker/docker/api/types/service_update_response.go delete mode 100644 vendor/github.com/docker/docker/api/types/stats.go delete mode 100644 vendor/github.com/docker/docker/api/types/strslice/strslice.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/common.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/config.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/container.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/network.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/node.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/runtime.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/secret.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/service.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/swarm.go delete mode 100644 vendor/github.com/docker/docker/api/types/swarm/task.go delete mode 100644 vendor/github.com/docker/docker/api/types/time/duration_convert.go delete mode 100644 vendor/github.com/docker/docker/api/types/time/timestamp.go delete mode 100644 vendor/github.com/docker/docker/api/types/types.go delete mode 100644 vendor/github.com/docker/docker/api/types/versions/README.md delete mode 100644 vendor/github.com/docker/docker/api/types/versions/compare.go delete mode 100644 vendor/github.com/docker/docker/api/types/volume.go delete mode 100644 vendor/github.com/docker/docker/api/types/volume/volume_create.go delete mode 100644 vendor/github.com/docker/docker/api/types/volume/volume_list.go delete mode 100644 vendor/github.com/docker/docker/client/README.md delete mode 100644 vendor/github.com/docker/docker/client/build_cancel.go delete mode 100644 vendor/github.com/docker/docker/client/build_prune.go delete mode 100644 vendor/github.com/docker/docker/client/checkpoint_create.go delete mode 100644 vendor/github.com/docker/docker/client/checkpoint_delete.go delete mode 100644 vendor/github.com/docker/docker/client/checkpoint_list.go delete mode 100644 vendor/github.com/docker/docker/client/client.go delete mode 100644 vendor/github.com/docker/docker/client/client_deprecated.go delete mode 100644 vendor/github.com/docker/docker/client/client_unix.go delete mode 100644 vendor/github.com/docker/docker/client/client_windows.go delete mode 100644 vendor/github.com/docker/docker/client/config_create.go delete mode 100644 vendor/github.com/docker/docker/client/config_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/config_list.go delete mode 100644 vendor/github.com/docker/docker/client/config_remove.go delete mode 100644 vendor/github.com/docker/docker/client/config_update.go delete mode 100644 vendor/github.com/docker/docker/client/container_attach.go delete mode 100644 vendor/github.com/docker/docker/client/container_commit.go delete mode 100644 vendor/github.com/docker/docker/client/container_copy.go delete mode 100644 vendor/github.com/docker/docker/client/container_create.go delete mode 100644 vendor/github.com/docker/docker/client/container_diff.go delete mode 100644 vendor/github.com/docker/docker/client/container_exec.go delete mode 100644 vendor/github.com/docker/docker/client/container_export.go delete mode 100644 vendor/github.com/docker/docker/client/container_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/container_kill.go delete mode 100644 vendor/github.com/docker/docker/client/container_list.go delete mode 100644 vendor/github.com/docker/docker/client/container_logs.go delete mode 100644 vendor/github.com/docker/docker/client/container_pause.go delete mode 100644 vendor/github.com/docker/docker/client/container_prune.go delete mode 100644 vendor/github.com/docker/docker/client/container_remove.go delete mode 100644 vendor/github.com/docker/docker/client/container_rename.go delete mode 100644 vendor/github.com/docker/docker/client/container_resize.go delete mode 100644 vendor/github.com/docker/docker/client/container_restart.go delete mode 100644 vendor/github.com/docker/docker/client/container_start.go delete mode 100644 vendor/github.com/docker/docker/client/container_stats.go delete mode 100644 vendor/github.com/docker/docker/client/container_stop.go delete mode 100644 vendor/github.com/docker/docker/client/container_top.go delete mode 100644 vendor/github.com/docker/docker/client/container_unpause.go delete mode 100644 vendor/github.com/docker/docker/client/container_update.go delete mode 100644 vendor/github.com/docker/docker/client/container_wait.go delete mode 100644 vendor/github.com/docker/docker/client/disk_usage.go delete mode 100644 vendor/github.com/docker/docker/client/distribution_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/errors.go delete mode 100644 vendor/github.com/docker/docker/client/events.go delete mode 100644 vendor/github.com/docker/docker/client/hijack.go delete mode 100644 vendor/github.com/docker/docker/client/image_build.go delete mode 100644 vendor/github.com/docker/docker/client/image_create.go delete mode 100644 vendor/github.com/docker/docker/client/image_history.go delete mode 100644 vendor/github.com/docker/docker/client/image_import.go delete mode 100644 vendor/github.com/docker/docker/client/image_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/image_list.go delete mode 100644 vendor/github.com/docker/docker/client/image_load.go delete mode 100644 vendor/github.com/docker/docker/client/image_prune.go delete mode 100644 vendor/github.com/docker/docker/client/image_pull.go delete mode 100644 vendor/github.com/docker/docker/client/image_push.go delete mode 100644 vendor/github.com/docker/docker/client/image_remove.go delete mode 100644 vendor/github.com/docker/docker/client/image_save.go delete mode 100644 vendor/github.com/docker/docker/client/image_search.go delete mode 100644 vendor/github.com/docker/docker/client/image_tag.go delete mode 100644 vendor/github.com/docker/docker/client/info.go delete mode 100644 vendor/github.com/docker/docker/client/interface.go delete mode 100644 vendor/github.com/docker/docker/client/interface_experimental.go delete mode 100644 vendor/github.com/docker/docker/client/interface_stable.go delete mode 100644 vendor/github.com/docker/docker/client/login.go delete mode 100644 vendor/github.com/docker/docker/client/network_connect.go delete mode 100644 vendor/github.com/docker/docker/client/network_create.go delete mode 100644 vendor/github.com/docker/docker/client/network_disconnect.go delete mode 100644 vendor/github.com/docker/docker/client/network_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/network_list.go delete mode 100644 vendor/github.com/docker/docker/client/network_prune.go delete mode 100644 vendor/github.com/docker/docker/client/network_remove.go delete mode 100644 vendor/github.com/docker/docker/client/node_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/node_list.go delete mode 100644 vendor/github.com/docker/docker/client/node_remove.go delete mode 100644 vendor/github.com/docker/docker/client/node_update.go delete mode 100644 vendor/github.com/docker/docker/client/options.go delete mode 100644 vendor/github.com/docker/docker/client/ping.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_create.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_disable.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_enable.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_install.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_list.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_push.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_remove.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_set.go delete mode 100644 vendor/github.com/docker/docker/client/plugin_upgrade.go delete mode 100644 vendor/github.com/docker/docker/client/request.go delete mode 100644 vendor/github.com/docker/docker/client/secret_create.go delete mode 100644 vendor/github.com/docker/docker/client/secret_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/secret_list.go delete mode 100644 vendor/github.com/docker/docker/client/secret_remove.go delete mode 100644 vendor/github.com/docker/docker/client/secret_update.go delete mode 100644 vendor/github.com/docker/docker/client/service_create.go delete mode 100644 vendor/github.com/docker/docker/client/service_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/service_list.go delete mode 100644 vendor/github.com/docker/docker/client/service_logs.go delete mode 100644 vendor/github.com/docker/docker/client/service_remove.go delete mode 100644 vendor/github.com/docker/docker/client/service_update.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_get_unlock_key.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_init.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_join.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_leave.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_unlock.go delete mode 100644 vendor/github.com/docker/docker/client/swarm_update.go delete mode 100644 vendor/github.com/docker/docker/client/task_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/task_list.go delete mode 100644 vendor/github.com/docker/docker/client/task_logs.go delete mode 100644 vendor/github.com/docker/docker/client/transport.go delete mode 100644 vendor/github.com/docker/docker/client/utils.go delete mode 100644 vendor/github.com/docker/docker/client/version.go delete mode 100644 vendor/github.com/docker/docker/client/volume_create.go delete mode 100644 vendor/github.com/docker/docker/client/volume_inspect.go delete mode 100644 vendor/github.com/docker/docker/client/volume_list.go delete mode 100644 vendor/github.com/docker/docker/client/volume_prune.go delete mode 100644 vendor/github.com/docker/docker/client/volume_remove.go delete mode 100644 vendor/github.com/docker/docker/errdefs/defs.go delete mode 100644 vendor/github.com/docker/docker/errdefs/doc.go delete mode 100644 vendor/github.com/docker/docker/errdefs/helpers.go delete mode 100644 vendor/github.com/docker/docker/errdefs/http_helpers.go delete mode 100644 vendor/github.com/docker/docker/errdefs/is.go delete mode 100644 vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go delete mode 100644 vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go delete mode 100644 vendor/github.com/docker/go-connections/LICENSE delete mode 100644 vendor/github.com/docker/go-connections/nat/nat.go delete mode 100644 vendor/github.com/docker/go-connections/nat/parse.go delete mode 100644 vendor/github.com/docker/go-connections/nat/sort.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/README.md delete mode 100644 vendor/github.com/docker/go-connections/sockets/inmem_socket.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/proxy.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/sockets.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/sockets_unix.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/sockets_windows.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/tcp_socket.go delete mode 100644 vendor/github.com/docker/go-connections/sockets/unix_socket.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/config.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go delete mode 100644 vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go delete mode 100644 vendor/github.com/google/cadvisor/container/docker/client.go delete mode 100644 vendor/github.com/google/cadvisor/container/docker/docker.go delete mode 100644 vendor/github.com/google/cadvisor/container/docker/factory.go delete mode 100644 vendor/github.com/google/cadvisor/container/docker/handler.go delete mode 100644 vendor/github.com/google/cadvisor/container/docker/install/install.go delete mode 100644 vendor/github.com/google/cadvisor/container/docker/plugin.go delete mode 100644 vendor/github.com/google/cadvisor/container/docker/utils/docker.go delete mode 100644 vendor/github.com/google/cadvisor/zfs/watcher.go delete mode 100644 vendor/github.com/morikuni/aec/LICENSE delete mode 100644 vendor/github.com/morikuni/aec/README.md delete mode 100644 vendor/github.com/morikuni/aec/aec.go delete mode 100644 vendor/github.com/morikuni/aec/ansi.go delete mode 100644 vendor/github.com/morikuni/aec/builder.go delete mode 100644 vendor/github.com/morikuni/aec/sample.gif delete mode 100644 vendor/github.com/morikuni/aec/sgr.go delete mode 100644 vendor/github.com/opencontainers/image-spec/LICENSE delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/version.go delete mode 100644 vendor/github.com/opencontainers/image-spec/specs-go/versioned.go delete mode 100644 vendor/golang.org/x/net/internal/socks/client.go delete mode 100644 vendor/golang.org/x/net/internal/socks/socks.go delete mode 100644 vendor/golang.org/x/net/proxy/dial.go delete mode 100644 vendor/golang.org/x/net/proxy/direct.go delete mode 100644 vendor/golang.org/x/net/proxy/per_host.go delete mode 100644 vendor/golang.org/x/net/proxy/proxy.go delete mode 100644 vendor/golang.org/x/net/proxy/socks5.go delete mode 100644 vendor/k8s.io/utils/net/ebtables/ebtables.go diff --git a/vendor/github.com/containerd/containerd/errdefs/errors.go b/vendor/github.com/containerd/containerd/errdefs/errors.go deleted file mode 100644 index 05a35228ca4..00000000000 --- a/vendor/github.com/containerd/containerd/errdefs/errors.go +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -// Package errdefs defines the common errors used throughout containerd -// packages. -// -// Use with errors.Wrap and error.Wrapf to add context to an error. -// -// To detect an error class, use the IsXXX functions to tell whether an error -// is of a certain type. -// -// The functions ToGRPC and FromGRPC can be used to map server-side and -// client-side errors to the correct types. -package errdefs - -import ( - "context" - - "github.com/pkg/errors" -) - -// Definitions of common error types used throughout containerd. All containerd -// errors returned by most packages will map into one of these errors classes. -// Packages should return errors of these types when they want to instruct a -// client to take a particular action. -// -// For the most part, we just try to provide local grpc errors. Most conditions -// map very well to those defined by grpc. -var ( - ErrUnknown = errors.New("unknown") // used internally to represent a missed mapping. - ErrInvalidArgument = errors.New("invalid argument") - ErrNotFound = errors.New("not found") - ErrAlreadyExists = errors.New("already exists") - ErrFailedPrecondition = errors.New("failed precondition") - ErrUnavailable = errors.New("unavailable") - ErrNotImplemented = errors.New("not implemented") // represents not supported and unimplemented -) - -// IsInvalidArgument returns true if the error is due to an invalid argument -func IsInvalidArgument(err error) bool { - return errors.Is(err, ErrInvalidArgument) -} - -// IsNotFound returns true if the error is due to a missing object -func IsNotFound(err error) bool { - return errors.Is(err, ErrNotFound) -} - -// IsAlreadyExists returns true if the error is due to an already existing -// metadata item -func IsAlreadyExists(err error) bool { - return errors.Is(err, ErrAlreadyExists) -} - -// IsFailedPrecondition returns true if an operation could not proceed to the -// lack of a particular condition -func IsFailedPrecondition(err error) bool { - return errors.Is(err, ErrFailedPrecondition) -} - -// IsUnavailable returns true if the error is due to a resource being unavailable -func IsUnavailable(err error) bool { - return errors.Is(err, ErrUnavailable) -} - -// IsNotImplemented returns true if the error is due to not being implemented -func IsNotImplemented(err error) bool { - return errors.Is(err, ErrNotImplemented) -} - -// IsCanceled returns true if the error is due to `context.Canceled`. -func IsCanceled(err error) bool { - return errors.Is(err, context.Canceled) -} - -// IsDeadlineExceeded returns true if the error is due to -// `context.DeadlineExceeded`. -func IsDeadlineExceeded(err error) bool { - return errors.Is(err, context.DeadlineExceeded) -} diff --git a/vendor/github.com/containerd/containerd/errdefs/grpc.go b/vendor/github.com/containerd/containerd/errdefs/grpc.go deleted file mode 100644 index 209f63bd0fc..00000000000 --- a/vendor/github.com/containerd/containerd/errdefs/grpc.go +++ /dev/null @@ -1,147 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package errdefs - -import ( - "context" - "strings" - - "github.com/pkg/errors" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// ToGRPC will attempt to map the backend containerd error into a grpc error, -// using the original error message as a description. -// -// Further information may be extracted from certain errors depending on their -// type. -// -// If the error is unmapped, the original error will be returned to be handled -// by the regular grpc error handling stack. -func ToGRPC(err error) error { - if err == nil { - return nil - } - - if isGRPCError(err) { - // error has already been mapped to grpc - return err - } - - switch { - case IsInvalidArgument(err): - return status.Errorf(codes.InvalidArgument, err.Error()) - case IsNotFound(err): - return status.Errorf(codes.NotFound, err.Error()) - case IsAlreadyExists(err): - return status.Errorf(codes.AlreadyExists, err.Error()) - case IsFailedPrecondition(err): - return status.Errorf(codes.FailedPrecondition, err.Error()) - case IsUnavailable(err): - return status.Errorf(codes.Unavailable, err.Error()) - case IsNotImplemented(err): - return status.Errorf(codes.Unimplemented, err.Error()) - case IsCanceled(err): - return status.Errorf(codes.Canceled, err.Error()) - case IsDeadlineExceeded(err): - return status.Errorf(codes.DeadlineExceeded, err.Error()) - } - - return err -} - -// ToGRPCf maps the error to grpc error codes, assembling the formatting string -// and combining it with the target error string. -// -// This is equivalent to errors.ToGRPC(errors.Wrapf(err, format, args...)) -func ToGRPCf(err error, format string, args ...interface{}) error { - return ToGRPC(errors.Wrapf(err, format, args...)) -} - -// FromGRPC returns the underlying error from a grpc service based on the grpc error code -func FromGRPC(err error) error { - if err == nil { - return nil - } - - var cls error // divide these into error classes, becomes the cause - - switch code(err) { - case codes.InvalidArgument: - cls = ErrInvalidArgument - case codes.AlreadyExists: - cls = ErrAlreadyExists - case codes.NotFound: - cls = ErrNotFound - case codes.Unavailable: - cls = ErrUnavailable - case codes.FailedPrecondition: - cls = ErrFailedPrecondition - case codes.Unimplemented: - cls = ErrNotImplemented - case codes.Canceled: - cls = context.Canceled - case codes.DeadlineExceeded: - cls = context.DeadlineExceeded - default: - cls = ErrUnknown - } - - msg := rebaseMessage(cls, err) - if msg != "" { - err = errors.Wrap(cls, msg) - } else { - err = errors.WithStack(cls) - } - - return err -} - -// rebaseMessage removes the repeats for an error at the end of an error -// string. This will happen when taking an error over grpc then remapping it. -// -// Effectively, we just remove the string of cls from the end of err if it -// appears there. -func rebaseMessage(cls error, err error) string { - desc := errDesc(err) - clss := cls.Error() - if desc == clss { - return "" - } - - return strings.TrimSuffix(desc, ": "+clss) -} - -func isGRPCError(err error) bool { - _, ok := status.FromError(err) - return ok -} - -func code(err error) codes.Code { - if s, ok := status.FromError(err); ok { - return s.Code() - } - return codes.Unknown -} - -func errDesc(err error) string { - if s, ok := status.FromError(err); ok { - return s.Message() - } - return err.Error() -} diff --git a/vendor/github.com/containerd/containerd/log/context.go b/vendor/github.com/containerd/containerd/log/context.go deleted file mode 100644 index 21599c4fd64..00000000000 --- a/vendor/github.com/containerd/containerd/log/context.go +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package log - -import ( - "context" - - "github.com/sirupsen/logrus" -) - -var ( - // G is an alias for GetLogger. - // - // We may want to define this locally to a package to get package tagged log - // messages. - G = GetLogger - - // L is an alias for the standard logger. - L = logrus.NewEntry(logrus.StandardLogger()) -) - -type ( - loggerKey struct{} -) - -// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to -// ensure the formatted time is always the same number of characters. -const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00" - -// WithLogger returns a new context with the provided logger. Use in -// combination with logger.WithField(s) for great effect. -func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context { - return context.WithValue(ctx, loggerKey{}, logger) -} - -// GetLogger retrieves the current logger from the context. If no logger is -// available, the default logger is returned. -func GetLogger(ctx context.Context) *logrus.Entry { - logger := ctx.Value(loggerKey{}) - - if logger == nil { - return L - } - - return logger.(*logrus.Entry) -} diff --git a/vendor/github.com/containerd/containerd/platforms/compare.go b/vendor/github.com/containerd/containerd/platforms/compare.go deleted file mode 100644 index 3ad22a10d0c..00000000000 --- a/vendor/github.com/containerd/containerd/platforms/compare.go +++ /dev/null @@ -1,229 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package platforms - -import specs "github.com/opencontainers/image-spec/specs-go/v1" - -// MatchComparer is able to match and compare platforms to -// filter and sort platforms. -type MatchComparer interface { - Matcher - - Less(specs.Platform, specs.Platform) bool -} - -// Only returns a match comparer for a single platform -// using default resolution logic for the platform. -// -// For ARMv8, will also match ARMv7, ARMv6 and ARMv5 (for 32bit runtimes) -// For ARMv7, will also match ARMv6 and ARMv5 -// For ARMv6, will also match ARMv5 -func Only(platform specs.Platform) MatchComparer { - platform = Normalize(platform) - if platform.Architecture == "arm" { - if platform.Variant == "v8" { - return orderedPlatformComparer{ - matchers: []Matcher{ - &matcher{ - Platform: platform, - }, - &matcher{ - Platform: specs.Platform{ - Architecture: platform.Architecture, - OS: platform.OS, - OSVersion: platform.OSVersion, - OSFeatures: platform.OSFeatures, - Variant: "v7", - }, - }, - &matcher{ - Platform: specs.Platform{ - Architecture: platform.Architecture, - OS: platform.OS, - OSVersion: platform.OSVersion, - OSFeatures: platform.OSFeatures, - Variant: "v6", - }, - }, - &matcher{ - Platform: specs.Platform{ - Architecture: platform.Architecture, - OS: platform.OS, - OSVersion: platform.OSVersion, - OSFeatures: platform.OSFeatures, - Variant: "v5", - }, - }, - }, - } - } - if platform.Variant == "v7" { - return orderedPlatformComparer{ - matchers: []Matcher{ - &matcher{ - Platform: platform, - }, - &matcher{ - Platform: specs.Platform{ - Architecture: platform.Architecture, - OS: platform.OS, - OSVersion: platform.OSVersion, - OSFeatures: platform.OSFeatures, - Variant: "v6", - }, - }, - &matcher{ - Platform: specs.Platform{ - Architecture: platform.Architecture, - OS: platform.OS, - OSVersion: platform.OSVersion, - OSFeatures: platform.OSFeatures, - Variant: "v5", - }, - }, - }, - } - } - if platform.Variant == "v6" { - return orderedPlatformComparer{ - matchers: []Matcher{ - &matcher{ - Platform: platform, - }, - &matcher{ - Platform: specs.Platform{ - Architecture: platform.Architecture, - OS: platform.OS, - OSVersion: platform.OSVersion, - OSFeatures: platform.OSFeatures, - Variant: "v5", - }, - }, - }, - } - } - } - - return singlePlatformComparer{ - Matcher: &matcher{ - Platform: platform, - }, - } -} - -// Ordered returns a platform MatchComparer which matches any of the platforms -// but orders them in order they are provided. -func Ordered(platforms ...specs.Platform) MatchComparer { - matchers := make([]Matcher, len(platforms)) - for i := range platforms { - matchers[i] = NewMatcher(platforms[i]) - } - return orderedPlatformComparer{ - matchers: matchers, - } -} - -// Any returns a platform MatchComparer which matches any of the platforms -// with no preference for ordering. -func Any(platforms ...specs.Platform) MatchComparer { - matchers := make([]Matcher, len(platforms)) - for i := range platforms { - matchers[i] = NewMatcher(platforms[i]) - } - return anyPlatformComparer{ - matchers: matchers, - } -} - -// All is a platform MatchComparer which matches all platforms -// with preference for ordering. -var All MatchComparer = allPlatformComparer{} - -type singlePlatformComparer struct { - Matcher -} - -func (c singlePlatformComparer) Less(p1, p2 specs.Platform) bool { - return c.Match(p1) && !c.Match(p2) -} - -type orderedPlatformComparer struct { - matchers []Matcher -} - -func (c orderedPlatformComparer) Match(platform specs.Platform) bool { - for _, m := range c.matchers { - if m.Match(platform) { - return true - } - } - return false -} - -func (c orderedPlatformComparer) Less(p1 specs.Platform, p2 specs.Platform) bool { - for _, m := range c.matchers { - p1m := m.Match(p1) - p2m := m.Match(p2) - if p1m && !p2m { - return true - } - if p1m || p2m { - return false - } - } - return false -} - -type anyPlatformComparer struct { - matchers []Matcher -} - -func (c anyPlatformComparer) Match(platform specs.Platform) bool { - for _, m := range c.matchers { - if m.Match(platform) { - return true - } - } - return false -} - -func (c anyPlatformComparer) Less(p1, p2 specs.Platform) bool { - var p1m, p2m bool - for _, m := range c.matchers { - if !p1m && m.Match(p1) { - p1m = true - } - if !p2m && m.Match(p2) { - p2m = true - } - if p1m && p2m { - return false - } - } - // If one matches, and the other does, sort match first - return p1m && !p2m -} - -type allPlatformComparer struct{} - -func (allPlatformComparer) Match(specs.Platform) bool { - return true -} - -func (allPlatformComparer) Less(specs.Platform, specs.Platform) bool { - return false -} diff --git a/vendor/github.com/containerd/containerd/platforms/cpuinfo.go b/vendor/github.com/containerd/containerd/platforms/cpuinfo.go deleted file mode 100644 index db65a726b90..00000000000 --- a/vendor/github.com/containerd/containerd/platforms/cpuinfo.go +++ /dev/null @@ -1,122 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package platforms - -import ( - "bufio" - "os" - "runtime" - "strings" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" - "github.com/pkg/errors" -) - -// Present the ARM instruction set architecture, eg: v7, v8 -var cpuVariant string - -func init() { - if isArmArch(runtime.GOARCH) { - cpuVariant = getCPUVariant() - } else { - cpuVariant = "" - } -} - -// For Linux, the kernel has already detected the ABI, ISA and Features. -// So we don't need to access the ARM registers to detect platform information -// by ourselves. We can just parse these information from /proc/cpuinfo -func getCPUInfo(pattern string) (info string, err error) { - if !isLinuxOS(runtime.GOOS) { - return "", errors.Wrapf(errdefs.ErrNotImplemented, "getCPUInfo for OS %s", runtime.GOOS) - } - - cpuinfo, err := os.Open("/proc/cpuinfo") - if err != nil { - return "", err - } - defer cpuinfo.Close() - - // Start to Parse the Cpuinfo line by line. For SMP SoC, we parse - // the first core is enough. - scanner := bufio.NewScanner(cpuinfo) - for scanner.Scan() { - newline := scanner.Text() - list := strings.Split(newline, ":") - - if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) { - return strings.TrimSpace(list[1]), nil - } - } - - // Check whether the scanner encountered errors - err = scanner.Err() - if err != nil { - return "", err - } - - return "", errors.Wrapf(errdefs.ErrNotFound, "getCPUInfo for pattern: %s", pattern) -} - -func getCPUVariant() string { - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { - // Windows/Darwin only supports v7 for ARM32 and v8 for ARM64 and so we can use - // runtime.GOARCH to determine the variants - var variant string - switch runtime.GOARCH { - case "arm64": - variant = "v8" - case "arm": - variant = "v7" - default: - variant = "unknown" - } - - return variant - } - - variant, err := getCPUInfo("Cpu architecture") - if err != nil { - log.L.WithError(err).Error("failure getting variant") - return "" - } - - switch strings.ToLower(variant) { - case "8", "aarch64": - // special case: if running a 32-bit userspace on aarch64, the variant should be "v7" - if runtime.GOARCH == "arm" { - variant = "v7" - } else { - variant = "v8" - } - case "7", "7m", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)": - variant = "v7" - case "6", "6tej": - variant = "v6" - case "5", "5t", "5te", "5tej": - variant = "v5" - case "4", "4t": - variant = "v4" - case "3": - variant = "v3" - default: - variant = "unknown" - } - - return variant -} diff --git a/vendor/github.com/containerd/containerd/platforms/database.go b/vendor/github.com/containerd/containerd/platforms/database.go deleted file mode 100644 index 6ede94061eb..00000000000 --- a/vendor/github.com/containerd/containerd/platforms/database.go +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package platforms - -import ( - "runtime" - "strings" -) - -// isLinuxOS returns true if the operating system is Linux. -// -// The OS value should be normalized before calling this function. -func isLinuxOS(os string) bool { - return os == "linux" -} - -// These function are generated from https://golang.org/src/go/build/syslist.go. -// -// We use switch statements because they are slightly faster than map lookups -// and use a little less memory. - -// isKnownOS returns true if we know about the operating system. -// -// The OS value should be normalized before calling this function. -func isKnownOS(os string) bool { - switch os { - case "aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos", "js", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows", "zos": - return true - } - return false -} - -// isArmArch returns true if the architecture is ARM. -// -// The arch value should be normalized before being passed to this function. -func isArmArch(arch string) bool { - switch arch { - case "arm", "arm64": - return true - } - return false -} - -// isKnownArch returns true if we know about the architecture. -// -// The arch value should be normalized before being passed to this function. -func isKnownArch(arch string) bool { - switch arch { - case "386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be", "ppc64", "ppc64le", "mips", "mipsle", "mips64", "mips64le", "mips64p32", "mips64p32le", "ppc", "riscv", "riscv64", "s390", "s390x", "sparc", "sparc64", "wasm": - return true - } - return false -} - -func normalizeOS(os string) string { - if os == "" { - return runtime.GOOS - } - os = strings.ToLower(os) - - switch os { - case "macos": - os = "darwin" - } - return os -} - -// normalizeArch normalizes the architecture. -func normalizeArch(arch, variant string) (string, string) { - arch, variant = strings.ToLower(arch), strings.ToLower(variant) - switch arch { - case "i386": - arch = "386" - variant = "" - case "x86_64", "x86-64": - arch = "amd64" - variant = "" - case "aarch64", "arm64": - arch = "arm64" - switch variant { - case "8", "v8": - variant = "" - } - case "armhf": - arch = "arm" - variant = "v7" - case "armel": - arch = "arm" - variant = "v6" - case "arm": - switch variant { - case "", "7": - variant = "v7" - case "5", "6", "8": - variant = "v" + variant - } - } - - return arch, variant -} diff --git a/vendor/github.com/containerd/containerd/platforms/defaults.go b/vendor/github.com/containerd/containerd/platforms/defaults.go deleted file mode 100644 index a14d80e58cb..00000000000 --- a/vendor/github.com/containerd/containerd/platforms/defaults.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package platforms - -import ( - "runtime" - - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - -// DefaultString returns the default string specifier for the platform. -func DefaultString() string { - return Format(DefaultSpec()) -} - -// DefaultSpec returns the current platform's default platform specification. -func DefaultSpec() specs.Platform { - return specs.Platform{ - OS: runtime.GOOS, - Architecture: runtime.GOARCH, - // The Variant field will be empty if arch != ARM. - Variant: cpuVariant, - } -} diff --git a/vendor/github.com/containerd/containerd/platforms/defaults_unix.go b/vendor/github.com/containerd/containerd/platforms/defaults_unix.go deleted file mode 100644 index e8a7d5ffa0d..00000000000 --- a/vendor/github.com/containerd/containerd/platforms/defaults_unix.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build !windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package platforms - -// Default returns the default matcher for the platform. -func Default() MatchComparer { - return Only(DefaultSpec()) -} diff --git a/vendor/github.com/containerd/containerd/platforms/defaults_windows.go b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go deleted file mode 100644 index 0defbd36c04..00000000000 --- a/vendor/github.com/containerd/containerd/platforms/defaults_windows.go +++ /dev/null @@ -1,31 +0,0 @@ -// +build windows - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package platforms - -import ( - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - -// Default returns the default matcher for the platform. -func Default() MatchComparer { - return Ordered(DefaultSpec(), specs.Platform{ - OS: "linux", - Architecture: "amd64", - }) -} diff --git a/vendor/github.com/containerd/containerd/platforms/platforms.go b/vendor/github.com/containerd/containerd/platforms/platforms.go deleted file mode 100644 index 77d3f184ec1..00000000000 --- a/vendor/github.com/containerd/containerd/platforms/platforms.go +++ /dev/null @@ -1,278 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -// Package platforms provides a toolkit for normalizing, matching and -// specifying container platforms. -// -// Centered around OCI platform specifications, we define a string-based -// specifier syntax that can be used for user input. With a specifier, users -// only need to specify the parts of the platform that are relevant to their -// context, providing an operating system or architecture or both. -// -// How do I use this package? -// -// The vast majority of use cases should simply use the match function with -// user input. The first step is to parse a specifier into a matcher: -// -// m, err := Parse("linux") -// if err != nil { ... } -// -// Once you have a matcher, use it to match against the platform declared by a -// component, typically from an image or runtime. Since extracting an images -// platform is a little more involved, we'll use an example against the -// platform default: -// -// if ok := m.Match(Default()); !ok { /* doesn't match */ } -// -// This can be composed in loops for resolving runtimes or used as a filter for -// fetch and select images. -// -// More details of the specifier syntax and platform spec follow. -// -// Declaring Platform Support -// -// Components that have strict platform requirements should use the OCI -// platform specification to declare their support. Typically, this will be -// images and runtimes that should make these declaring which platform they -// support specifically. This looks roughly as follows: -// -// type Platform struct { -// Architecture string -// OS string -// Variant string -// } -// -// Most images and runtimes should at least set Architecture and OS, according -// to their GOARCH and GOOS values, respectively (follow the OCI image -// specification when in doubt). ARM should set variant under certain -// discussions, which are outlined below. -// -// Platform Specifiers -// -// While the OCI platform specifications provide a tool for components to -// specify structured information, user input typically doesn't need the full -// context and much can be inferred. To solve this problem, we introduced -// "specifiers". A specifier has the format -// `||/[/]`. The user can provide either the -// operating system or the architecture or both. -// -// An example of a common specifier is `linux/amd64`. If the host has a default -// of runtime that matches this, the user can simply provide the component that -// matters. For example, if a image provides amd64 and arm64 support, the -// operating system, `linux` can be inferred, so they only have to provide -// `arm64` or `amd64`. Similar behavior is implemented for operating systems, -// where the architecture may be known but a runtime may support images from -// different operating systems. -// -// Normalization -// -// Because not all users are familiar with the way the Go runtime represents -// platforms, several normalizations have been provided to make this package -// easier to user. -// -// The following are performed for architectures: -// -// Value Normalized -// aarch64 arm64 -// armhf arm -// armel arm/v6 -// i386 386 -// x86_64 amd64 -// x86-64 amd64 -// -// We also normalize the operating system `macos` to `darwin`. -// -// ARM Support -// -// To qualify ARM architecture, the Variant field is used to qualify the arm -// version. The most common arm version, v7, is represented without the variant -// unless it is explicitly provided. This is treated as equivalent to armhf. A -// previous architecture, armel, will be normalized to arm/v6. -// -// While these normalizations are provided, their support on arm platforms has -// not yet been fully implemented and tested. -package platforms - -import ( - "regexp" - "runtime" - "strconv" - "strings" - - "github.com/containerd/containerd/errdefs" - specs "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" -) - -var ( - specifierRe = regexp.MustCompile(`^[A-Za-z0-9_-]+$`) -) - -// Matcher matches platforms specifications, provided by an image or runtime. -type Matcher interface { - Match(platform specs.Platform) bool -} - -// NewMatcher returns a simple matcher based on the provided platform -// specification. The returned matcher only looks for equality based on os, -// architecture and variant. -// -// One may implement their own matcher if this doesn't provide the required -// functionality. -// -// Applications should opt to use `Match` over directly parsing specifiers. -func NewMatcher(platform specs.Platform) Matcher { - return &matcher{ - Platform: Normalize(platform), - } -} - -type matcher struct { - specs.Platform -} - -func (m *matcher) Match(platform specs.Platform) bool { - normalized := Normalize(platform) - return m.OS == normalized.OS && - m.Architecture == normalized.Architecture && - m.Variant == normalized.Variant -} - -func (m *matcher) String() string { - return Format(m.Platform) -} - -// Parse parses the platform specifier syntax into a platform declaration. -// -// Platform specifiers are in the format `||/[/]`. -// The minimum required information for a platform specifier is the operating -// system or architecture. If there is only a single string (no slashes), the -// value will be matched against the known set of operating systems, then fall -// back to the known set of architectures. The missing component will be -// inferred based on the local environment. -func Parse(specifier string) (specs.Platform, error) { - if strings.Contains(specifier, "*") { - // TODO(stevvooe): need to work out exact wildcard handling - return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: wildcards not yet supported", specifier) - } - - parts := strings.Split(specifier, "/") - - for _, part := range parts { - if !specifierRe.MatchString(part) { - return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q is an invalid component of %q: platform specifier component must match %q", part, specifier, specifierRe.String()) - } - } - - var p specs.Platform - switch len(parts) { - case 1: - // in this case, we will test that the value might be an OS, then look - // it up. If it is not known, we'll treat it as an architecture. Since - // we have very little information about the platform here, we are - // going to be a little more strict if we don't know about the argument - // value. - p.OS = normalizeOS(parts[0]) - if isKnownOS(p.OS) { - // picks a default architecture - p.Architecture = runtime.GOARCH - if p.Architecture == "arm" && cpuVariant != "v7" { - p.Variant = cpuVariant - } - - return p, nil - } - - p.Architecture, p.Variant = normalizeArch(parts[0], "") - if p.Architecture == "arm" && p.Variant == "v7" { - p.Variant = "" - } - if isKnownArch(p.Architecture) { - p.OS = runtime.GOOS - return p, nil - } - - return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: unknown operating system or architecture", specifier) - case 2: - // In this case, we treat as a regular os/arch pair. We don't care - // about whether or not we know of the platform. - p.OS = normalizeOS(parts[0]) - p.Architecture, p.Variant = normalizeArch(parts[1], "") - if p.Architecture == "arm" && p.Variant == "v7" { - p.Variant = "" - } - - return p, nil - case 3: - // we have a fully specified variant, this is rare - p.OS = normalizeOS(parts[0]) - p.Architecture, p.Variant = normalizeArch(parts[1], parts[2]) - if p.Architecture == "arm64" && p.Variant == "" { - p.Variant = "v8" - } - - return p, nil - } - - return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: cannot parse platform specifier", specifier) -} - -// MustParse is like Parses but panics if the specifier cannot be parsed. -// Simplifies initialization of global variables. -func MustParse(specifier string) specs.Platform { - p, err := Parse(specifier) - if err != nil { - panic("platform: Parse(" + strconv.Quote(specifier) + "): " + err.Error()) - } - return p -} - -// Format returns a string specifier from the provided platform specification. -func Format(platform specs.Platform) string { - if platform.OS == "" { - return "unknown" - } - - return joinNotEmpty(platform.OS, platform.Architecture, platform.Variant) -} - -func joinNotEmpty(s ...string) string { - var ss []string - for _, s := range s { - if s == "" { - continue - } - - ss = append(ss, s) - } - - return strings.Join(ss, "/") -} - -// Normalize validates and translate the platform to the canonical value. -// -// For example, if "Aarch64" is encountered, we change it to "arm64" or if -// "x86_64" is encountered, it becomes "amd64". -func Normalize(platform specs.Platform) specs.Platform { - platform.OS = normalizeOS(platform.OS) - platform.Architecture, platform.Variant = normalizeArch(platform.Architecture, platform.Variant) - - // these fields are deprecated, remove them - platform.OSFeatures = nil - platform.OSVersion = "" - - return platform -} diff --git a/vendor/github.com/containernetworking/cni/LICENSE b/vendor/github.com/containernetworking/cni/LICENSE deleted file mode 100644 index 8f71f43fee3..00000000000 --- a/vendor/github.com/containernetworking/cni/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/vendor/github.com/containernetworking/cni/libcni/api.go b/vendor/github.com/containernetworking/cni/libcni/api.go deleted file mode 100644 index 7e52bd83873..00000000000 --- a/vendor/github.com/containernetworking/cni/libcni/api.go +++ /dev/null @@ -1,673 +0,0 @@ -// Copyright 2015 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package libcni - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "github.com/containernetworking/cni/pkg/invoke" - "github.com/containernetworking/cni/pkg/types" - "github.com/containernetworking/cni/pkg/utils" - "github.com/containernetworking/cni/pkg/version" -) - -var ( - CacheDir = "/var/lib/cni" -) - -const ( - CNICacheV1 = "cniCacheV1" -) - -// A RuntimeConf holds the arguments to one invocation of a CNI plugin -// excepting the network configuration, with the nested exception that -// the `runtimeConfig` from the network configuration is included -// here. -type RuntimeConf struct { - ContainerID string - NetNS string - IfName string - Args [][2]string - // A dictionary of capability-specific data passed by the runtime - // to plugins as top-level keys in the 'runtimeConfig' dictionary - // of the plugin's stdin data. libcni will ensure that only keys - // in this map which match the capabilities of the plugin are passed - // to the plugin - CapabilityArgs map[string]interface{} - - // DEPRECATED. Will be removed in a future release. - CacheDir string -} - -type NetworkConfig struct { - Network *types.NetConf - Bytes []byte -} - -type NetworkConfigList struct { - Name string - CNIVersion string - DisableCheck bool - Plugins []*NetworkConfig - Bytes []byte -} - -type CNI interface { - AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) - CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error - DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error - GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) - GetNetworkListCachedConfig(net *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error) - - AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) - CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error - DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error - GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) - GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error) - - ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error) - ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error) -} - -type CNIConfig struct { - Path []string - exec invoke.Exec - cacheDir string -} - -// CNIConfig implements the CNI interface -var _ CNI = &CNIConfig{} - -// NewCNIConfig returns a new CNIConfig object that will search for plugins -// in the given paths and use the given exec interface to run those plugins, -// or if the exec interface is not given, will use a default exec handler. -func NewCNIConfig(path []string, exec invoke.Exec) *CNIConfig { - return NewCNIConfigWithCacheDir(path, "", exec) -} - -// NewCNIConfigWithCacheDir returns a new CNIConfig object that will search for plugins -// in the given paths use the given exec interface to run those plugins, -// or if the exec interface is not given, will use a default exec handler. -// The given cache directory will be used for temporary data storage when needed. -func NewCNIConfigWithCacheDir(path []string, cacheDir string, exec invoke.Exec) *CNIConfig { - return &CNIConfig{ - Path: path, - cacheDir: cacheDir, - exec: exec, - } -} - -func buildOneConfig(name, cniVersion string, orig *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (*NetworkConfig, error) { - var err error - - inject := map[string]interface{}{ - "name": name, - "cniVersion": cniVersion, - } - // Add previous plugin result - if prevResult != nil { - inject["prevResult"] = prevResult - } - - // Ensure every config uses the same name and version - orig, err = InjectConf(orig, inject) - if err != nil { - return nil, err - } - - return injectRuntimeConfig(orig, rt) -} - -// This function takes a libcni RuntimeConf structure and injects values into -// a "runtimeConfig" dictionary in the CNI network configuration JSON that -// will be passed to the plugin on stdin. -// -// Only "capabilities arguments" passed by the runtime are currently injected. -// These capabilities arguments are filtered through the plugin's advertised -// capabilities from its config JSON, and any keys in the CapabilityArgs -// matching plugin capabilities are added to the "runtimeConfig" dictionary -// sent to the plugin via JSON on stdin. For example, if the plugin's -// capabilities include "portMappings", and the CapabilityArgs map includes a -// "portMappings" key, that key and its value are added to the "runtimeConfig" -// dictionary to be passed to the plugin's stdin. -func injectRuntimeConfig(orig *NetworkConfig, rt *RuntimeConf) (*NetworkConfig, error) { - var err error - - rc := make(map[string]interface{}) - for capability, supported := range orig.Network.Capabilities { - if !supported { - continue - } - if data, ok := rt.CapabilityArgs[capability]; ok { - rc[capability] = data - } - } - - if len(rc) > 0 { - orig, err = InjectConf(orig, map[string]interface{}{"runtimeConfig": rc}) - if err != nil { - return nil, err - } - } - - return orig, nil -} - -// ensure we have a usable exec if the CNIConfig was not given one -func (c *CNIConfig) ensureExec() invoke.Exec { - if c.exec == nil { - c.exec = &invoke.DefaultExec{ - RawExec: &invoke.RawExec{Stderr: os.Stderr}, - PluginDecoder: version.PluginDecoder{}, - } - } - return c.exec -} - -type cachedInfo struct { - Kind string `json:"kind"` - ContainerID string `json:"containerId"` - Config []byte `json:"config"` - IfName string `json:"ifName"` - NetworkName string `json:"networkName"` - CniArgs [][2]string `json:"cniArgs,omitempty"` - CapabilityArgs map[string]interface{} `json:"capabilityArgs,omitempty"` - RawResult map[string]interface{} `json:"result,omitempty"` - Result types.Result `json:"-"` -} - -// getCacheDir returns the cache directory in this order: -// 1) global cacheDir from CNIConfig object -// 2) deprecated cacheDir from RuntimeConf object -// 3) fall back to default cache directory -func (c *CNIConfig) getCacheDir(rt *RuntimeConf) string { - if c.cacheDir != "" { - return c.cacheDir - } - if rt.CacheDir != "" { - return rt.CacheDir - } - return CacheDir -} - -func (c *CNIConfig) getCacheFilePath(netName string, rt *RuntimeConf) (string, error) { - if netName == "" || rt.ContainerID == "" || rt.IfName == "" { - return "", fmt.Errorf("cache file path requires network name (%q), container ID (%q), and interface name (%q)", netName, rt.ContainerID, rt.IfName) - } - return filepath.Join(c.getCacheDir(rt), "results", fmt.Sprintf("%s-%s-%s", netName, rt.ContainerID, rt.IfName)), nil -} - -func (c *CNIConfig) cacheAdd(result types.Result, config []byte, netName string, rt *RuntimeConf) error { - cached := cachedInfo{ - Kind: CNICacheV1, - ContainerID: rt.ContainerID, - Config: config, - IfName: rt.IfName, - NetworkName: netName, - CniArgs: rt.Args, - CapabilityArgs: rt.CapabilityArgs, - } - - // We need to get type.Result into cachedInfo as JSON map - // Marshal to []byte, then Unmarshal into cached.RawResult - data, err := json.Marshal(result) - if err != nil { - return err - } - - err = json.Unmarshal(data, &cached.RawResult) - if err != nil { - return err - } - - newBytes, err := json.Marshal(&cached) - if err != nil { - return err - } - - fname, err := c.getCacheFilePath(netName, rt) - if err != nil { - return err - } - if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil { - return err - } - - return ioutil.WriteFile(fname, newBytes, 0600) -} - -func (c *CNIConfig) cacheDel(netName string, rt *RuntimeConf) error { - fname, err := c.getCacheFilePath(netName, rt) - if err != nil { - // Ignore error - return nil - } - return os.Remove(fname) -} - -func (c *CNIConfig) getCachedConfig(netName string, rt *RuntimeConf) ([]byte, *RuntimeConf, error) { - var bytes []byte - - fname, err := c.getCacheFilePath(netName, rt) - if err != nil { - return nil, nil, err - } - bytes, err = ioutil.ReadFile(fname) - if err != nil { - // Ignore read errors; the cached result may not exist on-disk - return nil, nil, nil - } - - unmarshaled := cachedInfo{} - if err := json.Unmarshal(bytes, &unmarshaled); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal cached network %q config: %v", netName, err) - } - if unmarshaled.Kind != CNICacheV1 { - return nil, nil, fmt.Errorf("read cached network %q config has wrong kind: %v", netName, unmarshaled.Kind) - } - - newRt := *rt - if unmarshaled.CniArgs != nil { - newRt.Args = unmarshaled.CniArgs - } - newRt.CapabilityArgs = unmarshaled.CapabilityArgs - - return unmarshaled.Config, &newRt, nil -} - -func (c *CNIConfig) getLegacyCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) { - fname, err := c.getCacheFilePath(netName, rt) - if err != nil { - return nil, err - } - data, err := ioutil.ReadFile(fname) - if err != nil { - // Ignore read errors; the cached result may not exist on-disk - return nil, nil - } - - // Read the version of the cached result - decoder := version.ConfigDecoder{} - resultCniVersion, err := decoder.Decode(data) - if err != nil { - return nil, err - } - - // Ensure we can understand the result - result, err := version.NewResult(resultCniVersion, data) - if err != nil { - return nil, err - } - - // Convert to the config version to ensure plugins get prevResult - // in the same version as the config. The cached result version - // should match the config version unless the config was changed - // while the container was running. - result, err = result.GetAsVersion(cniVersion) - if err != nil && resultCniVersion != cniVersion { - return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err) - } - return result, err -} - -func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) { - fname, err := c.getCacheFilePath(netName, rt) - if err != nil { - return nil, err - } - fdata, err := ioutil.ReadFile(fname) - if err != nil { - // Ignore read errors; the cached result may not exist on-disk - return nil, nil - } - - cachedInfo := cachedInfo{} - if err := json.Unmarshal(fdata, &cachedInfo); err != nil || cachedInfo.Kind != CNICacheV1 { - return c.getLegacyCachedResult(netName, cniVersion, rt) - } - - newBytes, err := json.Marshal(&cachedInfo.RawResult) - if err != nil { - return nil, fmt.Errorf("failed to marshal cached network %q config: %v", netName, err) - } - - // Read the version of the cached result - decoder := version.ConfigDecoder{} - resultCniVersion, err := decoder.Decode(newBytes) - if err != nil { - return nil, err - } - - // Ensure we can understand the result - result, err := version.NewResult(resultCniVersion, newBytes) - if err != nil { - return nil, err - } - - // Convert to the config version to ensure plugins get prevResult - // in the same version as the config. The cached result version - // should match the config version unless the config was changed - // while the container was running. - result, err = result.GetAsVersion(cniVersion) - if err != nil && resultCniVersion != cniVersion { - return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err) - } - return result, err -} - -// GetNetworkListCachedResult returns the cached Result of the previous -// AddNetworkList() operation for a network list, or an error. -func (c *CNIConfig) GetNetworkListCachedResult(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) { - return c.getCachedResult(list.Name, list.CNIVersion, rt) -} - -// GetNetworkCachedResult returns the cached Result of the previous -// AddNetwork() operation for a network, or an error. -func (c *CNIConfig) GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) { - return c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) -} - -// GetNetworkListCachedConfig copies the input RuntimeConf to output -// RuntimeConf with fields updated with info from the cached Config. -func (c *CNIConfig) GetNetworkListCachedConfig(list *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error) { - return c.getCachedConfig(list.Name, rt) -} - -// GetNetworkCachedConfig copies the input RuntimeConf to output -// RuntimeConf with fields updated with info from the cached Config. -func (c *CNIConfig) GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error) { - return c.getCachedConfig(net.Network.Name, rt) -} - -func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) { - c.ensureExec() - pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path) - if err != nil { - return nil, err - } - if err := utils.ValidateContainerID(rt.ContainerID); err != nil { - return nil, err - } - if err := utils.ValidateNetworkName(name); err != nil { - return nil, err - } - if err := utils.ValidateInterfaceName(rt.IfName); err != nil { - return nil, err - } - - newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt) - if err != nil { - return nil, err - } - - return invoke.ExecPluginWithResult(ctx, pluginPath, newConf.Bytes, c.args("ADD", rt), c.exec) -} - -// AddNetworkList executes a sequence of plugins with the ADD command -func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) { - var err error - var result types.Result - for _, net := range list.Plugins { - result, err = c.addNetwork(ctx, list.Name, list.CNIVersion, net, result, rt) - if err != nil { - return nil, err - } - } - - if err = c.cacheAdd(result, list.Bytes, list.Name, rt); err != nil { - return nil, fmt.Errorf("failed to set network %q cached result: %v", list.Name, err) - } - - return result, nil -} - -func (c *CNIConfig) checkNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error { - c.ensureExec() - pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path) - if err != nil { - return err - } - - newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt) - if err != nil { - return err - } - - return invoke.ExecPluginWithoutResult(ctx, pluginPath, newConf.Bytes, c.args("CHECK", rt), c.exec) -} - -// CheckNetworkList executes a sequence of plugins with the CHECK command -func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) error { - // CHECK was added in CNI spec version 0.4.0 and higher - if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil { - return err - } else if !gtet { - return fmt.Errorf("configuration version %q does not support the CHECK command", list.CNIVersion) - } - - if list.DisableCheck { - return nil - } - - cachedResult, err := c.getCachedResult(list.Name, list.CNIVersion, rt) - if err != nil { - return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err) - } - - for _, net := range list.Plugins { - if err := c.checkNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil { - return err - } - } - - return nil -} - -func (c *CNIConfig) delNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error { - c.ensureExec() - pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path) - if err != nil { - return err - } - - newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt) - if err != nil { - return err - } - - return invoke.ExecPluginWithoutResult(ctx, pluginPath, newConf.Bytes, c.args("DEL", rt), c.exec) -} - -// DelNetworkList executes a sequence of plugins with the DEL command -func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) error { - var cachedResult types.Result - - // Cached result on DEL was added in CNI spec version 0.4.0 and higher - if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil { - return err - } else if gtet { - cachedResult, err = c.getCachedResult(list.Name, list.CNIVersion, rt) - if err != nil { - return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err) - } - } - - for i := len(list.Plugins) - 1; i >= 0; i-- { - net := list.Plugins[i] - if err := c.delNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil { - return err - } - } - _ = c.cacheDel(list.Name, rt) - - return nil -} - -// AddNetwork executes the plugin with the ADD command -func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) { - result, err := c.addNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, nil, rt) - if err != nil { - return nil, err - } - - if err = c.cacheAdd(result, net.Bytes, net.Network.Name, rt); err != nil { - return nil, fmt.Errorf("failed to set network %q cached result: %v", net.Network.Name, err) - } - - return result, nil -} - -// CheckNetwork executes the plugin with the CHECK command -func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error { - // CHECK was added in CNI spec version 0.4.0 and higher - if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil { - return err - } else if !gtet { - return fmt.Errorf("configuration version %q does not support the CHECK command", net.Network.CNIVersion) - } - - cachedResult, err := c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) - if err != nil { - return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err) - } - return c.checkNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt) -} - -// DelNetwork executes the plugin with the DEL command -func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error { - var cachedResult types.Result - - // Cached result on DEL was added in CNI spec version 0.4.0 and higher - if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil { - return err - } else if gtet { - cachedResult, err = c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) - if err != nil { - return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err) - } - } - - if err := c.delNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt); err != nil { - return err - } - _ = c.cacheDel(net.Network.Name, rt) - return nil -} - -// ValidateNetworkList checks that a configuration is reasonably valid. -// - all the specified plugins exist on disk -// - every plugin supports the desired version. -// -// Returns a list of all capabilities supported by the configuration, or error -func (c *CNIConfig) ValidateNetworkList(ctx context.Context, list *NetworkConfigList) ([]string, error) { - version := list.CNIVersion - - // holding map for seen caps (in case of duplicates) - caps := map[string]interface{}{} - - errs := []error{} - for _, net := range list.Plugins { - if err := c.validatePlugin(ctx, net.Network.Type, version); err != nil { - errs = append(errs, err) - } - for c, enabled := range net.Network.Capabilities { - if !enabled { - continue - } - caps[c] = struct{}{} - } - } - - if len(errs) > 0 { - return nil, fmt.Errorf("%v", errs) - } - - // make caps list - cc := make([]string, 0, len(caps)) - for c := range caps { - cc = append(cc, c) - } - - return cc, nil -} - -// ValidateNetwork checks that a configuration is reasonably valid. -// It uses the same logic as ValidateNetworkList) -// Returns a list of capabilities -func (c *CNIConfig) ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error) { - caps := []string{} - for c, ok := range net.Network.Capabilities { - if ok { - caps = append(caps, c) - } - } - if err := c.validatePlugin(ctx, net.Network.Type, net.Network.CNIVersion); err != nil { - return nil, err - } - return caps, nil -} - -// validatePlugin checks that an individual plugin's configuration is sane -func (c *CNIConfig) validatePlugin(ctx context.Context, pluginName, expectedVersion string) error { - c.ensureExec() - pluginPath, err := c.exec.FindInPath(pluginName, c.Path) - if err != nil { - return err - } - if expectedVersion == "" { - expectedVersion = "0.1.0" - } - - vi, err := invoke.GetVersionInfo(ctx, pluginPath, c.exec) - if err != nil { - return err - } - for _, vers := range vi.SupportedVersions() { - if vers == expectedVersion { - return nil - } - } - return fmt.Errorf("plugin %s does not support config version %q", pluginName, expectedVersion) -} - -// GetVersionInfo reports which versions of the CNI spec are supported by -// the given plugin. -func (c *CNIConfig) GetVersionInfo(ctx context.Context, pluginType string) (version.PluginInfo, error) { - c.ensureExec() - pluginPath, err := c.exec.FindInPath(pluginType, c.Path) - if err != nil { - return nil, err - } - - return invoke.GetVersionInfo(ctx, pluginPath, c.exec) -} - -// ===== -func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args { - return &invoke.Args{ - Command: action, - ContainerID: rt.ContainerID, - NetNS: rt.NetNS, - PluginArgs: rt.Args, - IfName: rt.IfName, - Path: strings.Join(c.Path, string(os.PathListSeparator)), - } -} diff --git a/vendor/github.com/containernetworking/cni/libcni/conf.go b/vendor/github.com/containernetworking/cni/libcni/conf.go deleted file mode 100644 index d8920cf8cd5..00000000000 --- a/vendor/github.com/containernetworking/cni/libcni/conf.go +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2015 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package libcni - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sort" -) - -type NotFoundError struct { - Dir string - Name string -} - -func (e NotFoundError) Error() string { - return fmt.Sprintf(`no net configuration with name "%s" in %s`, e.Name, e.Dir) -} - -type NoConfigsFoundError struct { - Dir string -} - -func (e NoConfigsFoundError) Error() string { - return fmt.Sprintf(`no net configurations found in %s`, e.Dir) -} - -func ConfFromBytes(bytes []byte) (*NetworkConfig, error) { - conf := &NetworkConfig{Bytes: bytes} - if err := json.Unmarshal(bytes, &conf.Network); err != nil { - return nil, fmt.Errorf("error parsing configuration: %s", err) - } - if conf.Network.Type == "" { - return nil, fmt.Errorf("error parsing configuration: missing 'type'") - } - return conf, nil -} - -func ConfFromFile(filename string) (*NetworkConfig, error) { - bytes, err := ioutil.ReadFile(filename) - if err != nil { - return nil, fmt.Errorf("error reading %s: %s", filename, err) - } - return ConfFromBytes(bytes) -} - -func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) { - rawList := make(map[string]interface{}) - if err := json.Unmarshal(bytes, &rawList); err != nil { - return nil, fmt.Errorf("error parsing configuration list: %s", err) - } - - rawName, ok := rawList["name"] - if !ok { - return nil, fmt.Errorf("error parsing configuration list: no name") - } - name, ok := rawName.(string) - if !ok { - return nil, fmt.Errorf("error parsing configuration list: invalid name type %T", rawName) - } - - var cniVersion string - rawVersion, ok := rawList["cniVersion"] - if ok { - cniVersion, ok = rawVersion.(string) - if !ok { - return nil, fmt.Errorf("error parsing configuration list: invalid cniVersion type %T", rawVersion) - } - } - - disableCheck := false - if rawDisableCheck, ok := rawList["disableCheck"]; ok { - disableCheck, ok = rawDisableCheck.(bool) - if !ok { - return nil, fmt.Errorf("error parsing configuration list: invalid disableCheck type %T", rawDisableCheck) - } - } - - list := &NetworkConfigList{ - Name: name, - DisableCheck: disableCheck, - CNIVersion: cniVersion, - Bytes: bytes, - } - - var plugins []interface{} - plug, ok := rawList["plugins"] - if !ok { - return nil, fmt.Errorf("error parsing configuration list: no 'plugins' key") - } - plugins, ok = plug.([]interface{}) - if !ok { - return nil, fmt.Errorf("error parsing configuration list: invalid 'plugins' type %T", plug) - } - if len(plugins) == 0 { - return nil, fmt.Errorf("error parsing configuration list: no plugins in list") - } - - for i, conf := range plugins { - newBytes, err := json.Marshal(conf) - if err != nil { - return nil, fmt.Errorf("failed to marshal plugin config %d: %v", i, err) - } - netConf, err := ConfFromBytes(newBytes) - if err != nil { - return nil, fmt.Errorf("failed to parse plugin config %d: %v", i, err) - } - list.Plugins = append(list.Plugins, netConf) - } - - return list, nil -} - -func ConfListFromFile(filename string) (*NetworkConfigList, error) { - bytes, err := ioutil.ReadFile(filename) - if err != nil { - return nil, fmt.Errorf("error reading %s: %s", filename, err) - } - return ConfListFromBytes(bytes) -} - -func ConfFiles(dir string, extensions []string) ([]string, error) { - // In part, adapted from rkt/networking/podenv.go#listFiles - files, err := ioutil.ReadDir(dir) - switch { - case err == nil: // break - case os.IsNotExist(err): - return nil, nil - default: - return nil, err - } - - confFiles := []string{} - for _, f := range files { - if f.IsDir() { - continue - } - fileExt := filepath.Ext(f.Name()) - for _, ext := range extensions { - if fileExt == ext { - confFiles = append(confFiles, filepath.Join(dir, f.Name())) - } - } - } - return confFiles, nil -} - -func LoadConf(dir, name string) (*NetworkConfig, error) { - files, err := ConfFiles(dir, []string{".conf", ".json"}) - switch { - case err != nil: - return nil, err - case len(files) == 0: - return nil, NoConfigsFoundError{Dir: dir} - } - sort.Strings(files) - - for _, confFile := range files { - conf, err := ConfFromFile(confFile) - if err != nil { - return nil, err - } - if conf.Network.Name == name { - return conf, nil - } - } - return nil, NotFoundError{dir, name} -} - -func LoadConfList(dir, name string) (*NetworkConfigList, error) { - files, err := ConfFiles(dir, []string{".conflist"}) - if err != nil { - return nil, err - } - sort.Strings(files) - - for _, confFile := range files { - conf, err := ConfListFromFile(confFile) - if err != nil { - return nil, err - } - if conf.Name == name { - return conf, nil - } - } - - // Try and load a network configuration file (instead of list) - // from the same name, then upconvert. - singleConf, err := LoadConf(dir, name) - if err != nil { - // A little extra logic so the error makes sense - if _, ok := err.(NoConfigsFoundError); len(files) != 0 && ok { - // Config lists found but no config files found - return nil, NotFoundError{dir, name} - } - - return nil, err - } - return ConfListFromConf(singleConf) -} - -func InjectConf(original *NetworkConfig, newValues map[string]interface{}) (*NetworkConfig, error) { - config := make(map[string]interface{}) - err := json.Unmarshal(original.Bytes, &config) - if err != nil { - return nil, fmt.Errorf("unmarshal existing network bytes: %s", err) - } - - for key, value := range newValues { - if key == "" { - return nil, fmt.Errorf("keys cannot be empty") - } - - if value == nil { - return nil, fmt.Errorf("key '%s' value must not be nil", key) - } - - config[key] = value - } - - newBytes, err := json.Marshal(config) - if err != nil { - return nil, err - } - - return ConfFromBytes(newBytes) -} - -// ConfListFromConf "upconverts" a network config in to a NetworkConfigList, -// with the single network as the only entry in the list. -func ConfListFromConf(original *NetworkConfig) (*NetworkConfigList, error) { - // Re-deserialize the config's json, then make a raw map configlist. - // This may seem a bit strange, but it's to make the Bytes fields - // actually make sense. Otherwise, the generated json is littered with - // golang default values. - - rawConfig := make(map[string]interface{}) - if err := json.Unmarshal(original.Bytes, &rawConfig); err != nil { - return nil, err - } - - rawConfigList := map[string]interface{}{ - "name": original.Network.Name, - "cniVersion": original.Network.CNIVersion, - "plugins": []interface{}{rawConfig}, - } - - b, err := json.Marshal(rawConfigList) - if err != nil { - return nil, err - } - return ConfListFromBytes(b) -} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go deleted file mode 100644 index 3cdb4bc8dad..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2015 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package invoke - -import ( - "fmt" - "os" - "strings" -) - -type CNIArgs interface { - // For use with os/exec; i.e., return nil to inherit the - // environment from this process - // For use in delegation; inherit the environment from this - // process and allow overrides - AsEnv() []string -} - -type inherited struct{} - -var inheritArgsFromEnv inherited - -func (*inherited) AsEnv() []string { - return nil -} - -func ArgsFromEnv() CNIArgs { - return &inheritArgsFromEnv -} - -type Args struct { - Command string - ContainerID string - NetNS string - PluginArgs [][2]string - PluginArgsStr string - IfName string - Path string -} - -// Args implements the CNIArgs interface -var _ CNIArgs = &Args{} - -func (args *Args) AsEnv() []string { - env := os.Environ() - pluginArgsStr := args.PluginArgsStr - if pluginArgsStr == "" { - pluginArgsStr = stringify(args.PluginArgs) - } - - // Duplicated values which come first will be overridden, so we must put the - // custom values in the end to avoid being overridden by the process environments. - env = append(env, - "CNI_COMMAND="+args.Command, - "CNI_CONTAINERID="+args.ContainerID, - "CNI_NETNS="+args.NetNS, - "CNI_ARGS="+pluginArgsStr, - "CNI_IFNAME="+args.IfName, - "CNI_PATH="+args.Path, - ) - return dedupEnv(env) -} - -// taken from rkt/networking/net_plugin.go -func stringify(pluginArgs [][2]string) string { - entries := make([]string, len(pluginArgs)) - - for i, kv := range pluginArgs { - entries[i] = strings.Join(kv[:], "=") - } - - return strings.Join(entries, ";") -} - -// DelegateArgs implements the CNIArgs interface -// used for delegation to inherit from environments -// and allow some overrides like CNI_COMMAND -var _ CNIArgs = &DelegateArgs{} - -type DelegateArgs struct { - Command string -} - -func (d *DelegateArgs) AsEnv() []string { - env := os.Environ() - - // The custom values should come in the end to override the existing - // process environment of the same key. - env = append(env, - "CNI_COMMAND="+d.Command, - ) - return dedupEnv(env) -} - -// dedupEnv returns a copy of env with any duplicates removed, in favor of later values. -// Items not of the normal environment "key=value" form are preserved unchanged. -func dedupEnv(env []string) []string { - out := make([]string, 0, len(env)) - envMap := map[string]string{} - - for _, kv := range env { - // find the first "=" in environment, if not, just keep it - eq := strings.Index(kv, "=") - if eq < 0 { - out = append(out, kv) - continue - } - envMap[kv[:eq]] = kv[eq+1:] - } - - for k, v := range envMap { - out = append(out, fmt.Sprintf("%s=%s", k, v)) - } - - return out -} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go b/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go deleted file mode 100644 index 8defe4dd398..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package invoke - -import ( - "context" - "os" - "path/filepath" - - "github.com/containernetworking/cni/pkg/types" -) - -func delegateCommon(delegatePlugin string, exec Exec) (string, Exec, error) { - if exec == nil { - exec = defaultExec - } - - paths := filepath.SplitList(os.Getenv("CNI_PATH")) - pluginPath, err := exec.FindInPath(delegatePlugin, paths) - if err != nil { - return "", nil, err - } - - return pluginPath, exec, nil -} - -// DelegateAdd calls the given delegate plugin with the CNI ADD action and -// JSON configuration -func DelegateAdd(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) (types.Result, error) { - pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) - if err != nil { - return nil, err - } - - // DelegateAdd will override the original "CNI_COMMAND" env from process with ADD - return ExecPluginWithResult(ctx, pluginPath, netconf, delegateArgs("ADD"), realExec) -} - -// DelegateCheck calls the given delegate plugin with the CNI CHECK action and -// JSON configuration -func DelegateCheck(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error { - pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) - if err != nil { - return err - } - - // DelegateCheck will override the original CNI_COMMAND env from process with CHECK - return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("CHECK"), realExec) -} - -// DelegateDel calls the given delegate plugin with the CNI DEL action and -// JSON configuration -func DelegateDel(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error { - pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) - if err != nil { - return err - } - - // DelegateDel will override the original CNI_COMMAND env from process with DEL - return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("DEL"), realExec) -} - -// return CNIArgs used by delegation -func delegateArgs(action string) *DelegateArgs { - return &DelegateArgs{ - Command: action, - } -} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go deleted file mode 100644 index 8e6d30b8290..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2015 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package invoke - -import ( - "context" - "fmt" - "os" - - "github.com/containernetworking/cni/pkg/types" - "github.com/containernetworking/cni/pkg/version" -) - -// Exec is an interface encapsulates all operations that deal with finding -// and executing a CNI plugin. Tests may provide a fake implementation -// to avoid writing fake plugins to temporary directories during the test. -type Exec interface { - ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) - FindInPath(plugin string, paths []string) (string, error) - Decode(jsonBytes []byte) (version.PluginInfo, error) -} - -// For example, a testcase could pass an instance of the following fakeExec -// object to ExecPluginWithResult() to verify the incoming stdin and environment -// and provide a tailored response: -// -//import ( -// "encoding/json" -// "path" -// "strings" -//) -// -//type fakeExec struct { -// version.PluginDecoder -//} -// -//func (f *fakeExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) { -// net := &types.NetConf{} -// err := json.Unmarshal(stdinData, net) -// if err != nil { -// return nil, fmt.Errorf("failed to unmarshal configuration: %v", err) -// } -// pluginName := path.Base(pluginPath) -// if pluginName != net.Type { -// return nil, fmt.Errorf("plugin name %q did not match config type %q", pluginName, net.Type) -// } -// for _, e := range environ { -// // Check environment for forced failure request -// parts := strings.Split(e, "=") -// if len(parts) > 0 && parts[0] == "FAIL" { -// return nil, fmt.Errorf("failed to execute plugin %s", pluginName) -// } -// } -// return []byte("{\"CNIVersion\":\"0.4.0\"}"), nil -//} -// -//func (f *fakeExec) FindInPath(plugin string, paths []string) (string, error) { -// if len(paths) > 0 { -// return path.Join(paths[0], plugin), nil -// } -// return "", fmt.Errorf("failed to find plugin %s in paths %v", plugin, paths) -//} - -func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) (types.Result, error) { - if exec == nil { - exec = defaultExec - } - - stdoutBytes, err := exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv()) - if err != nil { - return nil, err - } - - // Plugin must return result in same version as specified in netconf - versionDecoder := &version.ConfigDecoder{} - confVersion, err := versionDecoder.Decode(netconf) - if err != nil { - return nil, err - } - - return version.NewResult(confVersion, stdoutBytes) -} - -func ExecPluginWithoutResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) error { - if exec == nil { - exec = defaultExec - } - _, err := exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv()) - return err -} - -// GetVersionInfo returns the version information available about the plugin. -// For recent-enough plugins, it uses the information returned by the VERSION -// command. For older plugins which do not recognize that command, it reports -// version 0.1.0 -func GetVersionInfo(ctx context.Context, pluginPath string, exec Exec) (version.PluginInfo, error) { - if exec == nil { - exec = defaultExec - } - args := &Args{ - Command: "VERSION", - - // set fake values required by plugins built against an older version of skel - NetNS: "dummy", - IfName: "dummy", - Path: "dummy", - } - stdin := []byte(fmt.Sprintf(`{"cniVersion":%q}`, version.Current())) - stdoutBytes, err := exec.ExecPlugin(ctx, pluginPath, stdin, args.AsEnv()) - if err != nil { - if err.Error() == "unknown CNI_COMMAND: VERSION" { - return version.PluginSupports("0.1.0"), nil - } - return nil, err - } - - return exec.Decode(stdoutBytes) -} - -// DefaultExec is an object that implements the Exec interface which looks -// for and executes plugins from disk. -type DefaultExec struct { - *RawExec - version.PluginDecoder -} - -// DefaultExec implements the Exec interface -var _ Exec = &DefaultExec{} - -var defaultExec = &DefaultExec{ - RawExec: &RawExec{Stderr: os.Stderr}, -} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/find.go b/vendor/github.com/containernetworking/cni/pkg/invoke/find.go deleted file mode 100644 index e62029eb788..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/find.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2015 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package invoke - -import ( - "fmt" - "os" - "path/filepath" - "strings" -) - -// FindInPath returns the full path of the plugin by searching in the provided path -func FindInPath(plugin string, paths []string) (string, error) { - if plugin == "" { - return "", fmt.Errorf("no plugin name provided") - } - - if strings.ContainsRune(plugin, os.PathSeparator) { - return "", fmt.Errorf("invalid plugin name: %s", plugin) - } - - if len(paths) == 0 { - return "", fmt.Errorf("no paths provided") - } - - for _, path := range paths { - for _, fe := range ExecutableFileExtensions { - fullpath := filepath.Join(path, plugin) + fe - if fi, err := os.Stat(fullpath); err == nil && fi.Mode().IsRegular() { - return fullpath, nil - } - } - } - - return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths) -} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go b/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go deleted file mode 100644 index 9bcfb455367..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 CNI 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. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package invoke - -// Valid file extensions for plugin executables. -var ExecutableFileExtensions = []string{""} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go b/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go deleted file mode 100644 index 7665125b133..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package invoke - -// Valid file extensions for plugin executables. -var ExecutableFileExtensions = []string{".exe", ""} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go deleted file mode 100644 index 5ab5cc88576..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package invoke - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "os/exec" - "strings" - "time" - - "github.com/containernetworking/cni/pkg/types" -) - -type RawExec struct { - Stderr io.Writer -} - -func (e *RawExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) { - stdout := &bytes.Buffer{} - stderr := &bytes.Buffer{} - c := exec.CommandContext(ctx, pluginPath) - c.Env = environ - c.Stdin = bytes.NewBuffer(stdinData) - c.Stdout = stdout - c.Stderr = stderr - - // Retry the command on "text file busy" errors - for i := 0; i <= 5; i++ { - err := c.Run() - - // Command succeeded - if err == nil { - break - } - - // If the plugin is currently about to be written, then we wait a - // second and try it again - if strings.Contains(err.Error(), "text file busy") { - time.Sleep(time.Second) - continue - } - - // All other errors except than the busy text file - return nil, e.pluginErr(err, stdout.Bytes(), stderr.Bytes()) - } - - // Copy stderr to caller's buffer in case plugin printed to both - // stdout and stderr for some reason. Ignore failures as stderr is - // only informational. - if e.Stderr != nil && stderr.Len() > 0 { - _, _ = stderr.WriteTo(e.Stderr) - } - return stdout.Bytes(), nil -} - -func (e *RawExec) pluginErr(err error, stdout, stderr []byte) error { - emsg := types.Error{} - if len(stdout) == 0 { - if len(stderr) == 0 { - emsg.Msg = fmt.Sprintf("netplugin failed with no error message: %v", err) - } else { - emsg.Msg = fmt.Sprintf("netplugin failed: %q", string(stderr)) - } - } else if perr := json.Unmarshal(stdout, &emsg); perr != nil { - emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(stdout), perr) - } - return &emsg -} - -func (e *RawExec) FindInPath(plugin string, paths []string) (string, error) { - return FindInPath(plugin, paths) -} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go deleted file mode 100644 index 36f31678a8e..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types020 - -import ( - "encoding/json" - "fmt" - "io" - "net" - "os" - - "github.com/containernetworking/cni/pkg/types" -) - -const ImplementedSpecVersion string = "0.2.0" - -var SupportedVersions = []string{"", "0.1.0", ImplementedSpecVersion} - -// Compatibility types for CNI version 0.1.0 and 0.2.0 - -func NewResult(data []byte) (types.Result, error) { - result := &Result{} - if err := json.Unmarshal(data, result); err != nil { - return nil, err - } - return result, nil -} - -func GetResult(r types.Result) (*Result, error) { - // We expect version 0.1.0/0.2.0 results - result020, err := r.GetAsVersion(ImplementedSpecVersion) - if err != nil { - return nil, err - } - result, ok := result020.(*Result) - if !ok { - return nil, fmt.Errorf("failed to convert result") - } - return result, nil -} - -// Result is what gets returned from the plugin (via stdout) to the caller -type Result struct { - CNIVersion string `json:"cniVersion,omitempty"` - IP4 *IPConfig `json:"ip4,omitempty"` - IP6 *IPConfig `json:"ip6,omitempty"` - DNS types.DNS `json:"dns,omitempty"` -} - -func (r *Result) Version() string { - return ImplementedSpecVersion -} - -func (r *Result) GetAsVersion(version string) (types.Result, error) { - for _, supportedVersion := range SupportedVersions { - if version == supportedVersion { - r.CNIVersion = version - return r, nil - } - } - return nil, fmt.Errorf("cannot convert version %q to %s", SupportedVersions, version) -} - -func (r *Result) Print() error { - return r.PrintTo(os.Stdout) -} - -func (r *Result) PrintTo(writer io.Writer) error { - data, err := json.MarshalIndent(r, "", " ") - if err != nil { - return err - } - _, err = writer.Write(data) - return err -} - -// IPConfig contains values necessary to configure an interface -type IPConfig struct { - IP net.IPNet - Gateway net.IP - Routes []types.Route -} - -// net.IPNet is not JSON (un)marshallable so this duality is needed -// for our custom IPNet type - -// JSON (un)marshallable types -type ipConfig struct { - IP types.IPNet `json:"ip"` - Gateway net.IP `json:"gateway,omitempty"` - Routes []types.Route `json:"routes,omitempty"` -} - -func (c *IPConfig) MarshalJSON() ([]byte, error) { - ipc := ipConfig{ - IP: types.IPNet(c.IP), - Gateway: c.Gateway, - Routes: c.Routes, - } - - return json.Marshal(ipc) -} - -func (c *IPConfig) UnmarshalJSON(data []byte) error { - ipc := ipConfig{} - if err := json.Unmarshal(data, &ipc); err != nil { - return err - } - - c.IP = net.IPNet(ipc.IP) - c.Gateway = ipc.Gateway - c.Routes = ipc.Routes - return nil -} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/args.go b/vendor/github.com/containernetworking/cni/pkg/types/args.go deleted file mode 100644 index 4eac6489947..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/types/args.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2015 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "encoding" - "fmt" - "reflect" - "strings" -) - -// UnmarshallableBool typedef for builtin bool -// because builtin type's methods can't be declared -type UnmarshallableBool bool - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -// Returns boolean true if the string is "1" or "[Tt]rue" -// Returns boolean false if the string is "0" or "[Ff]alse" -func (b *UnmarshallableBool) UnmarshalText(data []byte) error { - s := strings.ToLower(string(data)) - switch s { - case "1", "true": - *b = true - case "0", "false": - *b = false - default: - return fmt.Errorf("boolean unmarshal error: invalid input %s", s) - } - return nil -} - -// UnmarshallableString typedef for builtin string -type UnmarshallableString string - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -// Returns the string -func (s *UnmarshallableString) UnmarshalText(data []byte) error { - *s = UnmarshallableString(data) - return nil -} - -// CommonArgs contains the IgnoreUnknown argument -// and must be embedded by all Arg structs -type CommonArgs struct { - IgnoreUnknown UnmarshallableBool `json:"ignoreunknown,omitempty"` -} - -// GetKeyField is a helper function to receive Values -// Values that represent a pointer to a struct -func GetKeyField(keyString string, v reflect.Value) reflect.Value { - return v.Elem().FieldByName(keyString) -} - -// UnmarshalableArgsError is used to indicate error unmarshalling args -// from the args-string in the form "K=V;K2=V2;..." -type UnmarshalableArgsError struct { - error -} - -// LoadArgs parses args from a string in the form "K=V;K2=V2;..." -func LoadArgs(args string, container interface{}) error { - if args == "" { - return nil - } - - containerValue := reflect.ValueOf(container) - - pairs := strings.Split(args, ";") - unknownArgs := []string{} - for _, pair := range pairs { - kv := strings.Split(pair, "=") - if len(kv) != 2 { - return fmt.Errorf("ARGS: invalid pair %q", pair) - } - keyString := kv[0] - valueString := kv[1] - keyField := GetKeyField(keyString, containerValue) - if !keyField.IsValid() { - unknownArgs = append(unknownArgs, pair) - continue - } - keyFieldIface := keyField.Addr().Interface() - u, ok := keyFieldIface.(encoding.TextUnmarshaler) - if !ok { - return UnmarshalableArgsError{fmt.Errorf( - "ARGS: cannot unmarshal into field '%s' - type '%s' does not implement encoding.TextUnmarshaler", - keyString, reflect.TypeOf(keyFieldIface))} - } - err := u.UnmarshalText([]byte(valueString)) - if err != nil { - return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err) - } - } - - isIgnoreUnknown := GetKeyField("IgnoreUnknown", containerValue).Bool() - if len(unknownArgs) > 0 && !isIgnoreUnknown { - return fmt.Errorf("ARGS: unknown args %q", unknownArgs) - } - return nil -} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go deleted file mode 100644 index 754cc6e722e..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package current - -import ( - "encoding/json" - "fmt" - "io" - "net" - "os" - - "github.com/containernetworking/cni/pkg/types" - "github.com/containernetworking/cni/pkg/types/020" -) - -const ImplementedSpecVersion string = "0.4.0" - -var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion} - -func NewResult(data []byte) (types.Result, error) { - result := &Result{} - if err := json.Unmarshal(data, result); err != nil { - return nil, err - } - return result, nil -} - -func GetResult(r types.Result) (*Result, error) { - resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion) - if err != nil { - return nil, err - } - result, ok := resultCurrent.(*Result) - if !ok { - return nil, fmt.Errorf("failed to convert result") - } - return result, nil -} - -var resultConverters = []struct { - versions []string - convert func(types.Result) (*Result, error) -}{ - {types020.SupportedVersions, convertFrom020}, - {SupportedVersions, convertFrom030}, -} - -func convertFrom020(result types.Result) (*Result, error) { - oldResult, err := types020.GetResult(result) - if err != nil { - return nil, err - } - - newResult := &Result{ - CNIVersion: ImplementedSpecVersion, - DNS: oldResult.DNS, - Routes: []*types.Route{}, - } - - if oldResult.IP4 != nil { - newResult.IPs = append(newResult.IPs, &IPConfig{ - Version: "4", - Address: oldResult.IP4.IP, - Gateway: oldResult.IP4.Gateway, - }) - for _, route := range oldResult.IP4.Routes { - newResult.Routes = append(newResult.Routes, &types.Route{ - Dst: route.Dst, - GW: route.GW, - }) - } - } - - if oldResult.IP6 != nil { - newResult.IPs = append(newResult.IPs, &IPConfig{ - Version: "6", - Address: oldResult.IP6.IP, - Gateway: oldResult.IP6.Gateway, - }) - for _, route := range oldResult.IP6.Routes { - newResult.Routes = append(newResult.Routes, &types.Route{ - Dst: route.Dst, - GW: route.GW, - }) - } - } - - return newResult, nil -} - -func convertFrom030(result types.Result) (*Result, error) { - newResult, ok := result.(*Result) - if !ok { - return nil, fmt.Errorf("failed to convert result") - } - newResult.CNIVersion = ImplementedSpecVersion - return newResult, nil -} - -func NewResultFromResult(result types.Result) (*Result, error) { - version := result.Version() - for _, converter := range resultConverters { - for _, supportedVersion := range converter.versions { - if version == supportedVersion { - return converter.convert(result) - } - } - } - return nil, fmt.Errorf("unsupported CNI result22 version %q", version) -} - -// Result is what gets returned from the plugin (via stdout) to the caller -type Result struct { - CNIVersion string `json:"cniVersion,omitempty"` - Interfaces []*Interface `json:"interfaces,omitempty"` - IPs []*IPConfig `json:"ips,omitempty"` - Routes []*types.Route `json:"routes,omitempty"` - DNS types.DNS `json:"dns,omitempty"` -} - -// Convert to the older 0.2.0 CNI spec Result type -func (r *Result) convertTo020() (*types020.Result, error) { - oldResult := &types020.Result{ - CNIVersion: types020.ImplementedSpecVersion, - DNS: r.DNS, - } - - for _, ip := range r.IPs { - // Only convert the first IP address of each version as 0.2.0 - // and earlier cannot handle multiple IP addresses - if ip.Version == "4" && oldResult.IP4 == nil { - oldResult.IP4 = &types020.IPConfig{ - IP: ip.Address, - Gateway: ip.Gateway, - } - } else if ip.Version == "6" && oldResult.IP6 == nil { - oldResult.IP6 = &types020.IPConfig{ - IP: ip.Address, - Gateway: ip.Gateway, - } - } - - if oldResult.IP4 != nil && oldResult.IP6 != nil { - break - } - } - - for _, route := range r.Routes { - is4 := route.Dst.IP.To4() != nil - if is4 && oldResult.IP4 != nil { - oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{ - Dst: route.Dst, - GW: route.GW, - }) - } else if !is4 && oldResult.IP6 != nil { - oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{ - Dst: route.Dst, - GW: route.GW, - }) - } - } - - if oldResult.IP4 == nil && oldResult.IP6 == nil { - return nil, fmt.Errorf("cannot convert: no valid IP addresses") - } - - return oldResult, nil -} - -func (r *Result) Version() string { - return ImplementedSpecVersion -} - -func (r *Result) GetAsVersion(version string) (types.Result, error) { - switch version { - case "0.3.0", "0.3.1", ImplementedSpecVersion: - r.CNIVersion = version - return r, nil - case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]: - return r.convertTo020() - } - return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version) -} - -func (r *Result) Print() error { - return r.PrintTo(os.Stdout) -} - -func (r *Result) PrintTo(writer io.Writer) error { - data, err := json.MarshalIndent(r, "", " ") - if err != nil { - return err - } - _, err = writer.Write(data) - return err -} - -// Convert this old version result to the current CNI version result -func (r *Result) Convert() (*Result, error) { - return r, nil -} - -// Interface contains values about the created interfaces -type Interface struct { - Name string `json:"name"` - Mac string `json:"mac,omitempty"` - Sandbox string `json:"sandbox,omitempty"` -} - -func (i *Interface) String() string { - return fmt.Sprintf("%+v", *i) -} - -// Int returns a pointer to the int value passed in. Used to -// set the IPConfig.Interface field. -func Int(v int) *int { - return &v -} - -// IPConfig contains values necessary to configure an IP address on an interface -type IPConfig struct { - // IP version, either "4" or "6" - Version string - // Index into Result structs Interfaces list - Interface *int - Address net.IPNet - Gateway net.IP -} - -func (i *IPConfig) String() string { - return fmt.Sprintf("%+v", *i) -} - -// JSON (un)marshallable types -type ipConfig struct { - Version string `json:"version"` - Interface *int `json:"interface,omitempty"` - Address types.IPNet `json:"address"` - Gateway net.IP `json:"gateway,omitempty"` -} - -func (c *IPConfig) MarshalJSON() ([]byte, error) { - ipc := ipConfig{ - Version: c.Version, - Interface: c.Interface, - Address: types.IPNet(c.Address), - Gateway: c.Gateway, - } - - return json.Marshal(ipc) -} - -func (c *IPConfig) UnmarshalJSON(data []byte) error { - ipc := ipConfig{} - if err := json.Unmarshal(data, &ipc); err != nil { - return err - } - - c.Version = ipc.Version - c.Interface = ipc.Interface - c.Address = net.IPNet(ipc.Address) - c.Gateway = ipc.Gateway - return nil -} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/types.go b/vendor/github.com/containernetworking/cni/pkg/types/types.go deleted file mode 100644 index 3fa757a5d22..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/types/types.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2015 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "encoding/json" - "fmt" - "io" - "net" - "os" -) - -// like net.IPNet but adds JSON marshalling and unmarshalling -type IPNet net.IPNet - -// ParseCIDR takes a string like "10.2.3.1/24" and -// return IPNet with "10.2.3.1" and /24 mask -func ParseCIDR(s string) (*net.IPNet, error) { - ip, ipn, err := net.ParseCIDR(s) - if err != nil { - return nil, err - } - - ipn.IP = ip - return ipn, nil -} - -func (n IPNet) MarshalJSON() ([]byte, error) { - return json.Marshal((*net.IPNet)(&n).String()) -} - -func (n *IPNet) UnmarshalJSON(data []byte) error { - var s string - if err := json.Unmarshal(data, &s); err != nil { - return err - } - - tmp, err := ParseCIDR(s) - if err != nil { - return err - } - - *n = IPNet(*tmp) - return nil -} - -// NetConf describes a network. -type NetConf struct { - CNIVersion string `json:"cniVersion,omitempty"` - - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - Capabilities map[string]bool `json:"capabilities,omitempty"` - IPAM IPAM `json:"ipam,omitempty"` - DNS DNS `json:"dns"` - - RawPrevResult map[string]interface{} `json:"prevResult,omitempty"` - PrevResult Result `json:"-"` -} - -type IPAM struct { - Type string `json:"type,omitempty"` -} - -// NetConfList describes an ordered list of networks. -type NetConfList struct { - CNIVersion string `json:"cniVersion,omitempty"` - - Name string `json:"name,omitempty"` - DisableCheck bool `json:"disableCheck,omitempty"` - Plugins []*NetConf `json:"plugins,omitempty"` -} - -type ResultFactoryFunc func([]byte) (Result, error) - -// Result is an interface that provides the result of plugin execution -type Result interface { - // The highest CNI specification result version the result supports - // without having to convert - Version() string - - // Returns the result converted into the requested CNI specification - // result version, or an error if conversion failed - GetAsVersion(version string) (Result, error) - - // Prints the result in JSON format to stdout - Print() error - - // Prints the result in JSON format to provided writer - PrintTo(writer io.Writer) error -} - -func PrintResult(result Result, version string) error { - newResult, err := result.GetAsVersion(version) - if err != nil { - return err - } - return newResult.Print() -} - -// DNS contains values interesting for DNS resolvers -type DNS struct { - Nameservers []string `json:"nameservers,omitempty"` - Domain string `json:"domain,omitempty"` - Search []string `json:"search,omitempty"` - Options []string `json:"options,omitempty"` -} - -type Route struct { - Dst net.IPNet - GW net.IP -} - -func (r *Route) String() string { - return fmt.Sprintf("%+v", *r) -} - -// Well known error codes -// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes -const ( - ErrUnknown uint = iota // 0 - ErrIncompatibleCNIVersion // 1 - ErrUnsupportedField // 2 - ErrUnknownContainer // 3 - ErrInvalidEnvironmentVariables // 4 - ErrIOFailure // 5 - ErrDecodingFailure // 6 - ErrInvalidNetworkConfig // 7 - ErrTryAgainLater uint = 11 - ErrInternal uint = 999 -) - -type Error struct { - Code uint `json:"code"` - Msg string `json:"msg"` - Details string `json:"details,omitempty"` -} - -func NewError(code uint, msg, details string) *Error { - return &Error{ - Code: code, - Msg: msg, - Details: details, - } -} - -func (e *Error) Error() string { - details := "" - if e.Details != "" { - details = fmt.Sprintf("; %v", e.Details) - } - return fmt.Sprintf("%v%v", e.Msg, details) -} - -func (e *Error) Print() error { - return prettyPrint(e) -} - -// net.IPNet is not JSON (un)marshallable so this duality is needed -// for our custom IPNet type - -// JSON (un)marshallable types -type route struct { - Dst IPNet `json:"dst"` - GW net.IP `json:"gw,omitempty"` -} - -func (r *Route) UnmarshalJSON(data []byte) error { - rt := route{} - if err := json.Unmarshal(data, &rt); err != nil { - return err - } - - r.Dst = net.IPNet(rt.Dst) - r.GW = rt.GW - return nil -} - -func (r Route) MarshalJSON() ([]byte, error) { - rt := route{ - Dst: IPNet(r.Dst), - GW: r.GW, - } - - return json.Marshal(rt) -} - -func prettyPrint(obj interface{}) error { - data, err := json.MarshalIndent(obj, "", " ") - if err != nil { - return err - } - _, err = os.Stdout.Write(data) - return err -} diff --git a/vendor/github.com/containernetworking/cni/pkg/utils/utils.go b/vendor/github.com/containernetworking/cni/pkg/utils/utils.go deleted file mode 100644 index b8ec3887459..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/utils/utils.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2019 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "bytes" - "fmt" - "regexp" - "unicode" - - "github.com/containernetworking/cni/pkg/types" -) - -const ( - // cniValidNameChars is the regexp used to validate valid characters in - // containerID and networkName - cniValidNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.\-]` - - // maxInterfaceNameLength is the length max of a valid interface name - maxInterfaceNameLength = 15 -) - -var cniReg = regexp.MustCompile(`^` + cniValidNameChars + `*$`) - -// ValidateContainerID will validate that the supplied containerID is not empty does not contain invalid characters -func ValidateContainerID(containerID string) *types.Error { - - if containerID == "" { - return types.NewError(types.ErrUnknownContainer, "missing containerID", "") - } - if !cniReg.MatchString(containerID) { - return types.NewError(types.ErrInvalidEnvironmentVariables, "invalid characters in containerID", containerID) - } - return nil -} - -// ValidateNetworkName will validate that the supplied networkName does not contain invalid characters -func ValidateNetworkName(networkName string) *types.Error { - - if networkName == "" { - return types.NewError(types.ErrInvalidNetworkConfig, "missing network name:", "") - } - if !cniReg.MatchString(networkName) { - return types.NewError(types.ErrInvalidNetworkConfig, "invalid characters found in network name", networkName) - } - return nil -} - -// ValidateInterfaceName will validate the interface name based on the three rules below -// 1. The name must not be empty -// 2. The name must be less than 16 characters -// 3. The name must not be "." or ".." -// 3. The name must not contain / or : or any whitespace characters -// ref to https://github.com/torvalds/linux/blob/master/net/core/dev.c#L1024 -func ValidateInterfaceName(ifName string) *types.Error { - if len(ifName) == 0 { - return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is empty", "") - } - if len(ifName) > maxInterfaceNameLength { - return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is too long", fmt.Sprintf("interface name should be less than %d characters", maxInterfaceNameLength+1)) - } - if ifName == "." || ifName == ".." { - return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is . or ..", "") - } - for _, r := range bytes.Runes([]byte(ifName)) { - if r == '/' || r == ':' || unicode.IsSpace(r) { - return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name contains / or : or whitespace characters", "") - } - } - - return nil -} diff --git a/vendor/github.com/containernetworking/cni/pkg/version/conf.go b/vendor/github.com/containernetworking/cni/pkg/version/conf.go deleted file mode 100644 index 3cca58bbeb8..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/version/conf.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package version - -import ( - "encoding/json" - "fmt" -) - -// ConfigDecoder can decode the CNI version available in network config data -type ConfigDecoder struct{} - -func (*ConfigDecoder) Decode(jsonBytes []byte) (string, error) { - var conf struct { - CNIVersion string `json:"cniVersion"` - } - err := json.Unmarshal(jsonBytes, &conf) - if err != nil { - return "", fmt.Errorf("decoding version from network config: %s", err) - } - if conf.CNIVersion == "" { - return "0.1.0", nil - } - return conf.CNIVersion, nil -} diff --git a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go deleted file mode 100644 index 1df427243f3..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package version - -import ( - "encoding/json" - "fmt" - "io" - "strconv" - "strings" -) - -// PluginInfo reports information about CNI versioning -type PluginInfo interface { - // SupportedVersions returns one or more CNI spec versions that the plugin - // supports. If input is provided in one of these versions, then the plugin - // promises to use the same CNI version in its response - SupportedVersions() []string - - // Encode writes this CNI version information as JSON to the given Writer - Encode(io.Writer) error -} - -type pluginInfo struct { - CNIVersion_ string `json:"cniVersion"` - SupportedVersions_ []string `json:"supportedVersions,omitempty"` -} - -// pluginInfo implements the PluginInfo interface -var _ PluginInfo = &pluginInfo{} - -func (p *pluginInfo) Encode(w io.Writer) error { - return json.NewEncoder(w).Encode(p) -} - -func (p *pluginInfo) SupportedVersions() []string { - return p.SupportedVersions_ -} - -// PluginSupports returns a new PluginInfo that will report the given versions -// as supported -func PluginSupports(supportedVersions ...string) PluginInfo { - if len(supportedVersions) < 1 { - panic("programmer error: you must support at least one version") - } - return &pluginInfo{ - CNIVersion_: Current(), - SupportedVersions_: supportedVersions, - } -} - -// PluginDecoder can decode the response returned by a plugin's VERSION command -type PluginDecoder struct{} - -func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) { - var info pluginInfo - err := json.Unmarshal(jsonBytes, &info) - if err != nil { - return nil, fmt.Errorf("decoding version info: %s", err) - } - if info.CNIVersion_ == "" { - return nil, fmt.Errorf("decoding version info: missing field cniVersion") - } - if len(info.SupportedVersions_) == 0 { - if info.CNIVersion_ == "0.2.0" { - return PluginSupports("0.1.0", "0.2.0"), nil - } - return nil, fmt.Errorf("decoding version info: missing field supportedVersions") - } - return &info, nil -} - -// ParseVersion parses a version string like "3.0.1" or "0.4.5" into major, -// minor, and micro numbers or returns an error -func ParseVersion(version string) (int, int, int, error) { - var major, minor, micro int - if version == "" { - return -1, -1, -1, fmt.Errorf("invalid version %q: the version is empty", version) - } - - parts := strings.Split(version, ".") - if len(parts) >= 4 { - return -1, -1, -1, fmt.Errorf("invalid version %q: too many parts", version) - } - - major, err := strconv.Atoi(parts[0]) - if err != nil { - return -1, -1, -1, fmt.Errorf("failed to convert major version part %q: %v", parts[0], err) - } - - if len(parts) >= 2 { - minor, err = strconv.Atoi(parts[1]) - if err != nil { - return -1, -1, -1, fmt.Errorf("failed to convert minor version part %q: %v", parts[1], err) - } - } - - if len(parts) >= 3 { - micro, err = strconv.Atoi(parts[2]) - if err != nil { - return -1, -1, -1, fmt.Errorf("failed to convert micro version part %q: %v", parts[2], err) - } - } - - return major, minor, micro, nil -} - -// GreaterThanOrEqualTo takes two string versions, parses them into major/minor/micro -// numbers, and compares them to determine whether the first version is greater -// than or equal to the second -func GreaterThanOrEqualTo(version, otherVersion string) (bool, error) { - firstMajor, firstMinor, firstMicro, err := ParseVersion(version) - if err != nil { - return false, err - } - - secondMajor, secondMinor, secondMicro, err := ParseVersion(otherVersion) - if err != nil { - return false, err - } - - if firstMajor > secondMajor { - return true, nil - } else if firstMajor == secondMajor { - if firstMinor > secondMinor { - return true, nil - } else if firstMinor == secondMinor && firstMicro >= secondMicro { - return true, nil - } - } - return false, nil -} diff --git a/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go b/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go deleted file mode 100644 index 25c3810b2aa..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package version - -import "fmt" - -type ErrorIncompatible struct { - Config string - Supported []string -} - -func (e *ErrorIncompatible) Details() string { - return fmt.Sprintf("config is %q, plugin supports %q", e.Config, e.Supported) -} - -func (e *ErrorIncompatible) Error() string { - return fmt.Sprintf("incompatible CNI versions: %s", e.Details()) -} - -type Reconciler struct{} - -func (r *Reconciler) Check(configVersion string, pluginInfo PluginInfo) *ErrorIncompatible { - return r.CheckRaw(configVersion, pluginInfo.SupportedVersions()) -} - -func (*Reconciler) CheckRaw(configVersion string, supportedVersions []string) *ErrorIncompatible { - for _, supportedVersion := range supportedVersions { - if configVersion == supportedVersion { - return nil - } - } - - return &ErrorIncompatible{ - Config: configVersion, - Supported: supportedVersions, - } -} diff --git a/vendor/github.com/containernetworking/cni/pkg/version/version.go b/vendor/github.com/containernetworking/cni/pkg/version/version.go deleted file mode 100644 index 8f3508e61f3..00000000000 --- a/vendor/github.com/containernetworking/cni/pkg/version/version.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package version - -import ( - "encoding/json" - "fmt" - - "github.com/containernetworking/cni/pkg/types" - "github.com/containernetworking/cni/pkg/types/020" - "github.com/containernetworking/cni/pkg/types/current" -) - -// Current reports the version of the CNI spec implemented by this library -func Current() string { - return "0.4.0" -} - -// Legacy PluginInfo describes a plugin that is backwards compatible with the -// CNI spec version 0.1.0. In particular, a runtime compiled against the 0.1.0 -// library ought to work correctly with a plugin that reports support for -// Legacy versions. -// -// Any future CNI spec versions which meet this definition should be added to -// this list. -var Legacy = PluginSupports("0.1.0", "0.2.0") -var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0") - -var resultFactories = []struct { - supportedVersions []string - newResult types.ResultFactoryFunc -}{ - {current.SupportedVersions, current.NewResult}, - {types020.SupportedVersions, types020.NewResult}, -} - -// Finds a Result object matching the requested version (if any) and asks -// that object to parse the plugin result, returning an error if parsing failed. -func NewResult(version string, resultBytes []byte) (types.Result, error) { - reconciler := &Reconciler{} - for _, resultFactory := range resultFactories { - err := reconciler.CheckRaw(version, resultFactory.supportedVersions) - if err == nil { - // Result supports this version - return resultFactory.newResult(resultBytes) - } - } - - return nil, fmt.Errorf("unsupported CNI result version %q", version) -} - -// ParsePrevResult parses a prevResult in a NetConf structure and sets -// the NetConf's PrevResult member to the parsed Result object. -func ParsePrevResult(conf *types.NetConf) error { - if conf.RawPrevResult == nil { - return nil - } - - resultBytes, err := json.Marshal(conf.RawPrevResult) - if err != nil { - return fmt.Errorf("could not serialize prevResult: %v", err) - } - - conf.RawPrevResult = nil - conf.PrevResult, err = NewResult(conf.CNIVersion, resultBytes) - if err != nil { - return fmt.Errorf("could not parse prevResult: %v", err) - } - - return nil -} diff --git a/vendor/github.com/docker/distribution/registry/api/errcode/errors.go b/vendor/github.com/docker/distribution/registry/api/errcode/errors.go deleted file mode 100644 index 6d9bb4b62af..00000000000 --- a/vendor/github.com/docker/distribution/registry/api/errcode/errors.go +++ /dev/null @@ -1,267 +0,0 @@ -package errcode - -import ( - "encoding/json" - "fmt" - "strings" -) - -// ErrorCoder is the base interface for ErrorCode and Error allowing -// users of each to just call ErrorCode to get the real ID of each -type ErrorCoder interface { - ErrorCode() ErrorCode -} - -// ErrorCode represents the error type. The errors are serialized via strings -// and the integer format may change and should *never* be exported. -type ErrorCode int - -var _ error = ErrorCode(0) - -// ErrorCode just returns itself -func (ec ErrorCode) ErrorCode() ErrorCode { - return ec -} - -// Error returns the ID/Value -func (ec ErrorCode) Error() string { - // NOTE(stevvooe): Cannot use message here since it may have unpopulated args. - return strings.ToLower(strings.Replace(ec.String(), "_", " ", -1)) -} - -// Descriptor returns the descriptor for the error code. -func (ec ErrorCode) Descriptor() ErrorDescriptor { - d, ok := errorCodeToDescriptors[ec] - - if !ok { - return ErrorCodeUnknown.Descriptor() - } - - return d -} - -// String returns the canonical identifier for this error code. -func (ec ErrorCode) String() string { - return ec.Descriptor().Value -} - -// Message returned the human-readable error message for this error code. -func (ec ErrorCode) Message() string { - return ec.Descriptor().Message -} - -// MarshalText encodes the receiver into UTF-8-encoded text and returns the -// result. -func (ec ErrorCode) MarshalText() (text []byte, err error) { - return []byte(ec.String()), nil -} - -// UnmarshalText decodes the form generated by MarshalText. -func (ec *ErrorCode) UnmarshalText(text []byte) error { - desc, ok := idToDescriptors[string(text)] - - if !ok { - desc = ErrorCodeUnknown.Descriptor() - } - - *ec = desc.Code - - return nil -} - -// WithMessage creates a new Error struct based on the passed-in info and -// overrides the Message property. -func (ec ErrorCode) WithMessage(message string) Error { - return Error{ - Code: ec, - Message: message, - } -} - -// WithDetail creates a new Error struct based on the passed-in info and -// set the Detail property appropriately -func (ec ErrorCode) WithDetail(detail interface{}) Error { - return Error{ - Code: ec, - Message: ec.Message(), - }.WithDetail(detail) -} - -// WithArgs creates a new Error struct and sets the Args slice -func (ec ErrorCode) WithArgs(args ...interface{}) Error { - return Error{ - Code: ec, - Message: ec.Message(), - }.WithArgs(args...) -} - -// Error provides a wrapper around ErrorCode with extra Details provided. -type Error struct { - Code ErrorCode `json:"code"` - Message string `json:"message"` - Detail interface{} `json:"detail,omitempty"` - - // TODO(duglin): See if we need an "args" property so we can do the - // variable substitution right before showing the message to the user -} - -var _ error = Error{} - -// ErrorCode returns the ID/Value of this Error -func (e Error) ErrorCode() ErrorCode { - return e.Code -} - -// Error returns a human readable representation of the error. -func (e Error) Error() string { - return fmt.Sprintf("%s: %s", e.Code.Error(), e.Message) -} - -// WithDetail will return a new Error, based on the current one, but with -// some Detail info added -func (e Error) WithDetail(detail interface{}) Error { - return Error{ - Code: e.Code, - Message: e.Message, - Detail: detail, - } -} - -// WithArgs uses the passed-in list of interface{} as the substitution -// variables in the Error's Message string, but returns a new Error -func (e Error) WithArgs(args ...interface{}) Error { - return Error{ - Code: e.Code, - Message: fmt.Sprintf(e.Code.Message(), args...), - Detail: e.Detail, - } -} - -// ErrorDescriptor provides relevant information about a given error code. -type ErrorDescriptor struct { - // Code is the error code that this descriptor describes. - Code ErrorCode - - // Value provides a unique, string key, often captilized with - // underscores, to identify the error code. This value is used as the - // keyed value when serializing api errors. - Value string - - // Message is a short, human readable decription of the error condition - // included in API responses. - Message string - - // Description provides a complete account of the errors purpose, suitable - // for use in documentation. - Description string - - // HTTPStatusCode provides the http status code that is associated with - // this error condition. - HTTPStatusCode int -} - -// ParseErrorCode returns the value by the string error code. -// `ErrorCodeUnknown` will be returned if the error is not known. -func ParseErrorCode(value string) ErrorCode { - ed, ok := idToDescriptors[value] - if ok { - return ed.Code - } - - return ErrorCodeUnknown -} - -// Errors provides the envelope for multiple errors and a few sugar methods -// for use within the application. -type Errors []error - -var _ error = Errors{} - -func (errs Errors) Error() string { - switch len(errs) { - case 0: - return "" - case 1: - return errs[0].Error() - default: - msg := "errors:\n" - for _, err := range errs { - msg += err.Error() + "\n" - } - return msg - } -} - -// Len returns the current number of errors. -func (errs Errors) Len() int { - return len(errs) -} - -// MarshalJSON converts slice of error, ErrorCode or Error into a -// slice of Error - then serializes -func (errs Errors) MarshalJSON() ([]byte, error) { - var tmpErrs struct { - Errors []Error `json:"errors,omitempty"` - } - - for _, daErr := range errs { - var err Error - - switch daErr.(type) { - case ErrorCode: - err = daErr.(ErrorCode).WithDetail(nil) - case Error: - err = daErr.(Error) - default: - err = ErrorCodeUnknown.WithDetail(daErr) - - } - - // If the Error struct was setup and they forgot to set the - // Message field (meaning its "") then grab it from the ErrCode - msg := err.Message - if msg == "" { - msg = err.Code.Message() - } - - tmpErrs.Errors = append(tmpErrs.Errors, Error{ - Code: err.Code, - Message: msg, - Detail: err.Detail, - }) - } - - return json.Marshal(tmpErrs) -} - -// UnmarshalJSON deserializes []Error and then converts it into slice of -// Error or ErrorCode -func (errs *Errors) UnmarshalJSON(data []byte) error { - var tmpErrs struct { - Errors []Error - } - - if err := json.Unmarshal(data, &tmpErrs); err != nil { - return err - } - - var newErrs Errors - for _, daErr := range tmpErrs.Errors { - // If Message is empty or exactly matches the Code's message string - // then just use the Code, no need for a full Error struct - if daErr.Detail == nil && (daErr.Message == "" || daErr.Message == daErr.Code.Message()) { - // Error's w/o details get converted to ErrorCode - newErrs = append(newErrs, daErr.Code) - } else { - // Error's w/ details are untouched - newErrs = append(newErrs, Error{ - Code: daErr.Code, - Message: daErr.Message, - Detail: daErr.Detail, - }) - } - } - - *errs = newErrs - return nil -} diff --git a/vendor/github.com/docker/distribution/registry/api/errcode/handler.go b/vendor/github.com/docker/distribution/registry/api/errcode/handler.go deleted file mode 100644 index d77e70473e7..00000000000 --- a/vendor/github.com/docker/distribution/registry/api/errcode/handler.go +++ /dev/null @@ -1,40 +0,0 @@ -package errcode - -import ( - "encoding/json" - "net/http" -) - -// ServeJSON attempts to serve the errcode in a JSON envelope. It marshals err -// and sets the content-type header to 'application/json'. It will handle -// ErrorCoder and Errors, and if necessary will create an envelope. -func ServeJSON(w http.ResponseWriter, err error) error { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - var sc int - - switch errs := err.(type) { - case Errors: - if len(errs) < 1 { - break - } - - if err, ok := errs[0].(ErrorCoder); ok { - sc = err.ErrorCode().Descriptor().HTTPStatusCode - } - case ErrorCoder: - sc = errs.ErrorCode().Descriptor().HTTPStatusCode - err = Errors{err} // create an envelope. - default: - // We just have an unhandled error type, so just place in an envelope - // and move along. - err = Errors{err} - } - - if sc == 0 { - sc = http.StatusInternalServerError - } - - w.WriteHeader(sc) - - return json.NewEncoder(w).Encode(err) -} diff --git a/vendor/github.com/docker/distribution/registry/api/errcode/register.go b/vendor/github.com/docker/distribution/registry/api/errcode/register.go deleted file mode 100644 index d1e8826c6d7..00000000000 --- a/vendor/github.com/docker/distribution/registry/api/errcode/register.go +++ /dev/null @@ -1,138 +0,0 @@ -package errcode - -import ( - "fmt" - "net/http" - "sort" - "sync" -) - -var ( - errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{} - idToDescriptors = map[string]ErrorDescriptor{} - groupToDescriptors = map[string][]ErrorDescriptor{} -) - -var ( - // ErrorCodeUnknown is a generic error that can be used as a last - // resort if there is no situation-specific error message that can be used - ErrorCodeUnknown = Register("errcode", ErrorDescriptor{ - Value: "UNKNOWN", - Message: "unknown error", - Description: `Generic error returned when the error does not have an - API classification.`, - HTTPStatusCode: http.StatusInternalServerError, - }) - - // ErrorCodeUnsupported is returned when an operation is not supported. - ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{ - Value: "UNSUPPORTED", - Message: "The operation is unsupported.", - Description: `The operation was unsupported due to a missing - implementation or invalid set of parameters.`, - HTTPStatusCode: http.StatusMethodNotAllowed, - }) - - // ErrorCodeUnauthorized is returned if a request requires - // authentication. - ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{ - Value: "UNAUTHORIZED", - Message: "authentication required", - Description: `The access controller was unable to authenticate - the client. Often this will be accompanied by a - Www-Authenticate HTTP response header indicating how to - authenticate.`, - HTTPStatusCode: http.StatusUnauthorized, - }) - - // ErrorCodeDenied is returned if a client does not have sufficient - // permission to perform an action. - ErrorCodeDenied = Register("errcode", ErrorDescriptor{ - Value: "DENIED", - Message: "requested access to the resource is denied", - Description: `The access controller denied access for the - operation on a resource.`, - HTTPStatusCode: http.StatusForbidden, - }) - - // ErrorCodeUnavailable provides a common error to report unavailability - // of a service or endpoint. - ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{ - Value: "UNAVAILABLE", - Message: "service unavailable", - Description: "Returned when a service is not available", - HTTPStatusCode: http.StatusServiceUnavailable, - }) - - // ErrorCodeTooManyRequests is returned if a client attempts too many - // times to contact a service endpoint. - ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{ - Value: "TOOMANYREQUESTS", - Message: "too many requests", - Description: `Returned when a client attempts to contact a - service too many times`, - HTTPStatusCode: http.StatusTooManyRequests, - }) -) - -var nextCode = 1000 -var registerLock sync.Mutex - -// Register will make the passed-in error known to the environment and -// return a new ErrorCode -func Register(group string, descriptor ErrorDescriptor) ErrorCode { - registerLock.Lock() - defer registerLock.Unlock() - - descriptor.Code = ErrorCode(nextCode) - - if _, ok := idToDescriptors[descriptor.Value]; ok { - panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value)) - } - if _, ok := errorCodeToDescriptors[descriptor.Code]; ok { - panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code)) - } - - groupToDescriptors[group] = append(groupToDescriptors[group], descriptor) - errorCodeToDescriptors[descriptor.Code] = descriptor - idToDescriptors[descriptor.Value] = descriptor - - nextCode++ - return descriptor.Code -} - -type byValue []ErrorDescriptor - -func (a byValue) Len() int { return len(a) } -func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value } - -// GetGroupNames returns the list of Error group names that are registered -func GetGroupNames() []string { - keys := []string{} - - for k := range groupToDescriptors { - keys = append(keys, k) - } - sort.Strings(keys) - return keys -} - -// GetErrorCodeGroup returns the named group of error descriptors -func GetErrorCodeGroup(name string) []ErrorDescriptor { - desc := groupToDescriptors[name] - sort.Sort(byValue(desc)) - return desc -} - -// GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are -// registered, irrespective of what group they're in -func GetErrorAllDescriptors() []ErrorDescriptor { - result := []ErrorDescriptor{} - - for _, group := range GetGroupNames() { - result = append(result, GetErrorCodeGroup(group)...) - } - sort.Sort(byValue(result)) - return result -} diff --git a/vendor/github.com/docker/docker/AUTHORS b/vendor/github.com/docker/docker/AUTHORS deleted file mode 100644 index dffacff1120..00000000000 --- a/vendor/github.com/docker/docker/AUTHORS +++ /dev/null @@ -1,2175 +0,0 @@ -# This file lists all individuals having contributed content to the repository. -# For how it is generated, see `hack/generate-authors.sh`. - -Aanand Prasad -Aaron Davidson -Aaron Feng -Aaron Hnatiw -Aaron Huslage -Aaron L. Xu -Aaron Lehmann -Aaron Welch -Aaron.L.Xu -Abel Muiño -Abhijeet Kasurde -Abhinandan Prativadi -Abhinav Ajgaonkar -Abhishek Chanda -Abhishek Sharma -Abin Shahab -Adam Avilla -Adam Dobrawy -Adam Eijdenberg -Adam Kunk -Adam Miller -Adam Mills -Adam Pointer -Adam Singer -Adam Walz -Addam Hardy -Aditi Rajagopal -Aditya -Adnan Khan -Adolfo Ochagavía -Adria Casas -Adrian Moisey -Adrian Mouat -Adrian Oprea -Adrien Folie -Adrien Gallouët -Ahmed Kamal -Ahmet Alp Balkan -Aidan Feldman -Aidan Hobson Sayers -AJ Bowen -Ajey Charantimath -ajneu -Akash Gupta -Akhil Mohan -Akihiro Matsushima -Akihiro Suda -Akim Demaille -Akira Koyasu -Akshay Karle -Al Tobey -alambike -Alan Hoyle -Alan Scherger -Alan Thompson -Albert Callarisa -Albert Zhang -Albin Kerouanton -Alejandro González Hevia -Aleksa Sarai -Aleksandrs Fadins -Alena Prokharchyk -Alessandro Boch -Alessio Biancalana -Alex Chan -Alex Chen -Alex Coventry -Alex Crawford -Alex Ellis -Alex Gaynor -Alex Goodman -Alex Olshansky -Alex Samorukov -Alex Warhawk -Alexander Artemenko -Alexander Boyd -Alexander Larsson -Alexander Midlash -Alexander Morozov -Alexander Shopov -Alexandre Beslic -Alexandre Garnier -Alexandre González -Alexandre Jomin -Alexandru Sfirlogea -Alexei Margasov -Alexey Guskov -Alexey Kotlyarov -Alexey Shamrin -Alexis THOMAS -Alfred Landrum -Ali Dehghani -Alicia Lauerman -Alihan Demir -Allen Madsen -Allen Sun -almoehi -Alvaro Saurin -Alvin Deng -Alvin Richards -amangoel -Amen Belayneh -Amir Goldstein -Amit Bakshi -Amit Krishnan -Amit Shukla -Amr Gawish -Amy Lindburg -Anand Patil -AnandkumarPatel -Anatoly Borodin -Anca Iordache -Anchal Agrawal -Anda Xu -Anders Janmyr -Andre Dublin <81dublin@gmail.com> -Andre Granovsky -Andrea Denisse Gómez -Andrea Luzzardi -Andrea Turli -Andreas Elvers -Andreas Köhler -Andreas Savvides -Andreas Tiefenthaler -Andrei Gherzan -Andrei Vagin -Andrew C. Bodine -Andrew Clay Shafer -Andrew Duckworth -Andrew France -Andrew Gerrand -Andrew Guenther -Andrew He -Andrew Hsu -Andrew Kuklewicz -Andrew Macgregor -Andrew Macpherson -Andrew Martin -Andrew McDonnell -Andrew Munsell -Andrew Pennebaker -Andrew Po -Andrew Weiss -Andrew Williams -Andrews Medina -Andrey Kolomentsev -Andrey Petrov -Andrey Stolbovsky -André Martins -andy -Andy Chambers -andy diller -Andy Goldstein -Andy Kipp -Andy Rothfusz -Andy Smith -Andy Wilson -Anes Hasicic -Anil Belur -Anil Madhavapeddy -Ankit Jain -Ankush Agarwal -Anonmily -Anran Qiao -Anshul Pundir -Anthon van der Neut -Anthony Baire -Anthony Bishopric -Anthony Dahanne -Anthony Sottile -Anton Löfgren -Anton Nikitin -Anton Polonskiy -Anton Tiurin -Antonio Murdaca -Antonis Kalipetis -Antony Messerli -Anuj Bahuguna -Anusha Ragunathan -apocas -Arash Deshmeh -ArikaChen -Arko Dasgupta -Arnaud Lefebvre -Arnaud Porterie -Arnaud Rebillout -Arthur Barr -Arthur Gautier -Artur Meyster -Arun Gupta -Asad Saeeduddin -Asbjørn Enge -averagehuman -Avi Das -Avi Kivity -Avi Miller -Avi Vaid -ayoshitake -Azat Khuyiyakhmetov -Bardia Keyoumarsi -Barnaby Gray -Barry Allard -Bartłomiej Piotrowski -Bastiaan Bakker -bdevloed -Ben Bonnefoy -Ben Firshman -Ben Golub -Ben Gould -Ben Hall -Ben Sargent -Ben Severson -Ben Toews -Ben Wiklund -Benjamin Atkin -Benjamin Baker -Benjamin Boudreau -Benjamin Yolken -Benny Ng -Benoit Chesneau -Bernerd Schaefer -Bernhard M. Wiedemann -Bert Goethals -Bertrand Roussel -Bevisy Zhang -Bharath Thiruveedula -Bhiraj Butala -Bhumika Bayani -Bilal Amarni -Bill Wang -Bily Zhang -Bin Liu -Bingshen Wang -Blake Geno -Boaz Shuster -bobby abbott -Boqin Qin -Boris Pruessmann -Boshi Lian -Bouke Haarsma -Boyd Hemphill -boynux -Bradley Cicenas -Bradley Wright -Brandon Liu -Brandon Philips -Brandon Rhodes -Brendan Dixon -Brent Salisbury -Brett Higgins -Brett Kochendorfer -Brett Randall -Brian (bex) Exelbierd -Brian Bland -Brian DeHamer -Brian Dorsey -Brian Flad -Brian Goff -Brian McCallister -Brian Olsen -Brian Schwind -Brian Shumate -Brian Torres-Gil -Brian Trump -Brice Jaglin -Briehan Lombaard -Brielle Broder -Bruno Bigras -Bruno Binet -Bruno Gazzera -Bruno Renié -Bruno Tavares -Bryan Bess -Bryan Boreham -Bryan Matsuo -Bryan Murphy -Burke Libbey -Byung Kang -Caleb Spare -Calen Pennington -Cameron Boehmer -Cameron Spear -Campbell Allen -Candid Dauth -Cao Weiwei -Carl Henrik Lunde -Carl Loa Odin -Carl X. Su -Carlo Mion -Carlos Alexandro Becker -Carlos de Paula -Carlos Sanchez -Carol Fager-Higgins -Cary -Casey Bisson -Catalin Pirvu -Ce Gao -Cedric Davies -Cezar Sa Espinola -Chad Swenson -Chance Zibolski -Chander Govindarajan -Chanhun Jeong -Chao Wang -Charles Chan -Charles Hooper -Charles Law -Charles Lindsay -Charles Merriam -Charles Sarrazin -Charles Smith -Charlie Drage -Charlie Lewis -Chase Bolt -ChaYoung You -Chen Chao -Chen Chuanliang -Chen Hanxiao -Chen Min -Chen Mingjie -Chen Qiu -Cheng-mean Liu -Chengfei Shang -Chengguang Xu -chenyuzhu -Chetan Birajdar -Chewey -Chia-liang Kao -chli -Cholerae Hu -Chris Alfonso -Chris Armstrong -Chris Dias -Chris Dituri -Chris Fordham -Chris Gavin -Chris Gibson -Chris Khoo -Chris McKinnel -Chris McKinnel -Chris Price -Chris Seto -Chris Snow -Chris St. Pierre -Chris Stivers -Chris Swan -Chris Telfer -Chris Wahl -Chris Weyl -Chris White -Christian Berendt -Christian Brauner -Christian Böhme -Christian Muehlhaeuser -Christian Persson -Christian Rotzoll -Christian Simon -Christian Stefanescu -Christophe Mehay -Christophe Troestler -Christophe Vidal -Christopher Biscardi -Christopher Crone -Christopher Currie -Christopher Jones -Christopher Latham -Christopher Rigor -Christy Norman -Chun Chen -Ciro S. Costa -Clayton Coleman -Clinton Kitson -Cody Roseborough -Coenraad Loubser -Colin Dunklau -Colin Hebert -Colin Panisset -Colin Rice -Colin Walters -Collin Guarino -Colm Hally -companycy -Corbin Coleman -Corey Farrell -Cory Forsyth -cressie176 -CrimsonGlory -Cristian Ariza -Cristian Staretu -cristiano balducci -Cristina Yenyxe Gonzalez Garcia -Cruceru Calin-Cristian -CUI Wei -Cyprian Gracz -Cyril F -Daan van Berkel -Daehyeok Mun -Dafydd Crosby -dalanlan -Damian Smyth -Damien Nadé -Damien Nozay -Damjan Georgievski -Dan Anolik -Dan Buch -Dan Cotora -Dan Feldman -Dan Griffin -Dan Hirsch -Dan Keder -Dan Levy -Dan McPherson -Dan Stine -Dan Williams -Dani Hodovic -Dani Louca -Daniel Antlinger -Daniel Black -Daniel Dao -Daniel Exner -Daniel Farrell -Daniel Garcia -Daniel Gasienica -Daniel Grunwell -Daniel Helfand -Daniel Hiltgen -Daniel J Walsh -Daniel Menet -Daniel Mizyrycki -Daniel Nephin -Daniel Norberg -Daniel Nordberg -Daniel Robinson -Daniel S -Daniel Sweet -Daniel Von Fange -Daniel Watkins -Daniel X Moore -Daniel YC Lin -Daniel Zhang -Danny Berger -Danny Milosavljevic -Danny Yates -Danyal Khaliq -Darren Coxall -Darren Shepherd -Darren Stahl -Dattatraya Kumbhar -Davanum Srinivas -Dave Barboza -Dave Goodchild -Dave Henderson -Dave MacDonald -Dave Tucker -David Anderson -David Calavera -David Chung -David Corking -David Cramer -David Currie -David Davis -David Dooling -David Gageot -David Gebler -David Glasser -David Lawrence -David Lechner -David M. Karr -David Mackey -David Mat -David Mcanulty -David McKay -David P Hilton -David Pelaez -David R. Jenni -David Röthlisberger -David Sheets -David Sissitka -David Trott -David Wang <00107082@163.com> -David Williamson -David Xia -David Young -Davide Ceretti -Dawn Chen -dbdd -dcylabs -Debayan De -Deborah Gertrude Digges -deed02392 -Deep Debroy -Deng Guangxing -Deni Bertovic -Denis Defreyne -Denis Gladkikh -Denis Ollier -Dennis Chen -Dennis Chen -Dennis Docter -Derek -Derek -Derek Ch -Derek McGowan -Deric Crago -Deshi Xiao -devmeyster -Devon Estes -Devvyn Murphy -Dharmit Shah -Dhawal Yogesh Bhanushali -Diego Romero -Diego Siqueira -Dieter Reuter -Dillon Dixon -Dima Stopel -Dimitri John Ledkov -Dimitris Mandalidis -Dimitris Rozakis -Dimitry Andric -Dinesh Subhraveti -Ding Fei -Diogo Monica -DiuDiugirl -Djibril Koné -dkumor -Dmitri Logvinenko -Dmitri Shuralyov -Dmitry Demeshchuk -Dmitry Gusev -Dmitry Kononenko -Dmitry Sharshakov -Dmitry Shyshkin -Dmitry Smirnov -Dmitry V. Krivenok -Dmitry Vorobev -Dolph Mathews -Dominic Tubach -Dominic Yin -Dominik Dingel -Dominik Finkbeiner -Dominik Honnef -Don Kirkby -Don Kjer -Don Spaulding -Donald Huang -Dong Chen -Donghwa Kim -Donovan Jones -Doron Podoleanu -Doug Davis -Doug MacEachern -Doug Tangren -Douglas Curtis -Dr Nic Williams -dragon788 -Dražen Lučanin -Drew Erny -Drew Hubl -Dustin Sallings -Ed Costello -Edmund Wagner -Eiichi Tsukata -Eike Herzbach -Eivin Giske Skaaren -Eivind Uggedal -Elan Ruusamäe -Elango Sivanandam -Elena Morozova -Eli Uriegas -Elias Faxö -Elias Probst -Elijah Zupancic -eluck -Elvir Kuric -Emil Davtyan -Emil Hernvall -Emily Maier -Emily Rose -Emir Ozer -Enguerran -Eohyung Lee -epeterso -Eric Barch -Eric Curtin -Eric G. Noriega -Eric Hanchrow -Eric Lee -Eric Myhre -Eric Paris -Eric Rafaloff -Eric Rosenberg -Eric Sage -Eric Soderstrom -Eric Yang -Eric-Olivier Lamey -Erica Windisch -Erik Bray -Erik Dubbelboer -Erik Hollensbe -Erik Inge Bolsø -Erik Kristensen -Erik St. Martin -Erik Weathers -Erno Hopearuoho -Erwin van der Koogh -Ethan Bell -Ethan Mosbaugh -Euan Kemp -Eugen Krizo -Eugene Yakubovich -Evan Allrich -Evan Carmi -Evan Hazlett -Evan Krall -Evan Phoenix -Evan Wies -Evelyn Xu -Everett Toews -Evgeniy Makhrov -Evgeny Shmarnev -Evgeny Vereshchagin -Ewa Czechowska -Eystein Måløy Stenberg -ezbercih -Ezra Silvera -Fabian Kramm -Fabian Lauer -Fabian Raetz -Fabiano Rosas -Fabio Falci -Fabio Kung -Fabio Rapposelli -Fabio Rehm -Fabrizio Regini -Fabrizio Soppelsa -Faiz Khan -falmp -Fangming Fang -Fangyuan Gao <21551127@zju.edu.cn> -fanjiyun -Fareed Dudhia -Fathi Boudra -Federico Gimenez -Felipe Oliveira -Felipe Ruhland -Felix Abecassis -Felix Geisendörfer -Felix Hupfeld -Felix Rabe -Felix Ruess -Felix Schindler -Feng Yan -Fengtu Wang -Ferenc Szabo -Fernando -Fero Volar -Ferran Rodenas -Filipe Brandenburger -Filipe Oliveira -Flavio Castelli -Flavio Crisciani -Florian -Florian Klein -Florian Maier -Florian Noeding -Florian Schmaus -Florian Weingarten -Florin Asavoaie -Florin Patan -fonglh -Foysal Iqbal -Francesc Campoy -Francesco Mari -Francis Chuang -Francisco Carriedo -Francisco Souza -Frank Groeneveld -Frank Herrmann -Frank Macreery -Frank Rosquin -frankyang -Fred Lifton -Frederick F. Kautz IV -Frederik Loeffert -Frederik Nordahl Jul Sabroe -Freek Kalter -Frieder Bluemle -Fu JinLin -Félix Baylac-Jacqué -Félix Cantournet -Gabe Rosenhouse -Gabor Nagy -Gabriel Linder -Gabriel Monroy -Gabriel Nicolas Avellaneda -Gaetan de Villele -Galen Sampson -Gang Qiao -Gareth Rushgrove -Garrett Barboza -Gary Schaetz -Gaurav -Gaurav Singh -Gaël PORTAY -Genki Takiuchi -GennadySpb -Geoffrey Bachelet -Geon Kim -George Kontridze -George MacRorie -George Xie -Georgi Hristozov -Gereon Frey -German DZ -Gert van Valkenhoef -Gerwim Feiken -Ghislain Bourgeois -Giampaolo Mancini -Gianluca Borello -Gildas Cuisinier -Giovan Isa Musthofa -gissehel -Giuseppe Mazzotta -Gleb Fotengauer-Malinovskiy -Gleb M Borisov -Glyn Normington -GoBella -Goffert van Gool -Goldwyn Rodrigues -Gopikannan Venugopalsamy -Gosuke Miyashita -Gou Rao -Govinda Fichtner -Grant Millar -Grant Reaber -Graydon Hoare -Greg Fausak -Greg Pflaum -Greg Stephens -Greg Thornton -Grzegorz Jaśkiewicz -Guilhem Lettron -Guilherme Salgado -Guillaume Dufour -Guillaume J. Charmes -guoxiuyan -Guri -Gurjeet Singh -Guruprasad -Gustav Sinder -gwx296173 -Günter Zöchbauer -Haichao Yang -haikuoliu -Hakan Özler -Hamish Hutchings -Hannes Ljungberg -Hans Kristian Flaatten -Hans Rødtang -Hao Shu Wei -Hao Zhang <21521210@zju.edu.cn> -Harald Albers -Harald Niesche -Harley Laue -Harold Cooper -Harrison Turton -Harry Zhang -Harshal Patil -Harshal Patil -He Simei -He Xiaoxi -He Xin -heartlock <21521209@zju.edu.cn> -Hector Castro -Helen Xie -Henning Sprang -Hiroshi Hatake -Hiroyuki Sasagawa -Hobofan -Hollie Teal -Hong Xu -Hongbin Lu -Hongxu Jia -Honza Pokorny -Hsing-Hui Hsu -hsinko <21551195@zju.edu.cn> -Hu Keping -Hu Tao -HuanHuan Ye -Huanzhong Zhang -Huayi Zhang -Hugo Duncan -Hugo Marisco <0x6875676f@gmail.com> -Hunter Blanks -huqun -Huu Nguyen -hyeongkyu.lee -Hyzhou Zhy -Iago López Galeiras -Ian Babrou -Ian Bishop -Ian Bull -Ian Calvert -Ian Campbell -Ian Chen -Ian Lee -Ian Main -Ian Philpot -Ian Truslove -Iavael -Icaro Seara -Ignacio Capurro -Igor Dolzhikov -Igor Karpovich -Iliana Weller -Ilkka Laukkanen -Ilya Dmitrichenko -Ilya Gusev -Ilya Khlopotov -imre Fitos -inglesp -Ingo Gottwald -Innovimax -Isaac Dupree -Isabel Jimenez -Isaiah Grace -Isao Jonas -Iskander Sharipov -Ivan Babrou -Ivan Fraixedes -Ivan Grcic -Ivan Markin -J Bruni -J. Nunn -Jack Danger Canty -Jack Laxson -Jacob Atzen -Jacob Edelman -Jacob Tomlinson -Jacob Vallejo -Jacob Wen -Jaime Cepeda -Jaivish Kothari -Jake Champlin -Jake Moshenko -Jake Sanders -jakedt -James Allen -James Carey -James Carr -James DeFelice -James Harrison Fisher -James Kyburz -James Kyle -James Lal -James Mills -James Nesbitt -James Nugent -James Turnbull -James Watkins-Harvey -Jamie Hannaford -Jamshid Afshar -Jan Chren -Jan Keromnes -Jan Koprowski -Jan Pazdziora -Jan Toebes -Jan-Gerd Tenberge -Jan-Jaap Driessen -Jana Radhakrishnan -Jannick Fahlbusch -Januar Wayong -Jared Biel -Jared Hocutt -Jaroslaw Zabiello -jaseg -Jasmine Hegman -Jason A. Donenfeld -Jason Divock -Jason Giedymin -Jason Green -Jason Hall -Jason Heiss -Jason Livesay -Jason McVetta -Jason Plum -Jason Shepherd -Jason Smith -Jason Sommer -Jason Stangroome -jaxgeller -Jay -Jay -Jay Kamat -Jean Rouge -Jean-Baptiste Barth -Jean-Baptiste Dalido -Jean-Christophe Berthon -Jean-Paul Calderone -Jean-Pierre Huynh -Jean-Tiare Le Bigot -Jeeva S. Chelladhurai -Jeff Anderson -Jeff Hajewski -Jeff Johnston -Jeff Lindsay -Jeff Mickey -Jeff Minard -Jeff Nickoloff -Jeff Silberman -Jeff Welch -Jeffrey Bolle -Jeffrey Morgan -Jeffrey van Gogh -Jenny Gebske -Jeremy Chambers -Jeremy Grosser -Jeremy Price -Jeremy Qian -Jeremy Unruh -Jeremy Yallop -Jeroen Franse -Jeroen Jacobs -Jesse Dearing -Jesse Dubay -Jessica Frazelle -Jezeniel Zapanta -Jhon Honce -Ji.Zhilong -Jian Liao -Jian Zhang -Jiang Jinyang -Jie Luo -Jie Ma -Jihyun Hwang -Jilles Oldenbeuving -Jim Alateras -Jim Ehrismann -Jim Galasyn -Jim Minter -Jim Perrin -Jimmy Cuadra -Jimmy Puckett -Jimmy Song -Jinsoo Park -Jintao Zhang -Jiri Appl -Jiri Popelka -Jiuyue Ma -Jiří Župka -Joao Fernandes -Joao Trindade -Joe Beda -Joe Doliner -Joe Ferguson -Joe Gordon -Joe Shaw -Joe Van Dyk -Joel Friedly -Joel Handwell -Joel Hansson -Joel Wurtz -Joey Geiger -Joey Geiger -Joey Gibson -Joffrey F -Johan Euphrosine -Johan Rydberg -Johanan Lieberman -Johannes 'fish' Ziemke -John Costa -John Feminella -John Gardiner Myers -John Gossman -John Harris -John Howard -John Laswell -John Maguire -John Mulhausen -John OBrien III -John Starks -John Stephens -John Tims -John V. Martinez -John Warwick -John Willis -Jon Johnson -Jon Surrell -Jon Wedaman -Jonas Dohse -Jonas Heinrich -Jonas Pfenniger -Jonathan A. Schweder -Jonathan A. Sternberg -Jonathan Boulle -Jonathan Camp -Jonathan Choy -Jonathan Dowland -Jonathan Lebon -Jonathan Lomas -Jonathan McCrohan -Jonathan Mueller -Jonathan Pares -Jonathan Rudenberg -Jonathan Stoppani -Jonh Wendell -Joni Sar -Joost Cassee -Jordan Arentsen -Jordan Jennings -Jordan Sissel -Jorge Marin -Jorit Kleine-Möllhoff -Jose Diaz-Gonzalez -Joseph Anthony Pasquale Holsten -Joseph Hager -Joseph Kern -Joseph Rothrock -Josh -Josh Bodah -Josh Bonczkowski -Josh Chorlton -Josh Eveleth -Josh Hawn -Josh Horwitz -Josh Poimboeuf -Josh Soref -Josh Wilson -Josiah Kiehl -José Tomás Albornoz -Joyce Jang -JP -Julian Taylor -Julien Barbier -Julien Bisconti -Julien Bordellier -Julien Dubois -Julien Kassar -Julien Maitrehenry -Julien Pervillé -Julien Pivotto -Julio Guerra -Julio Montes -Jun-Ru Chang -Jussi Nummelin -Justas Brazauskas -Justen Martin -Justin Cormack -Justin Force -Justin Menga -Justin Plock -Justin Simonelis -Justin Terry -Justyn Temme -Jyrki Puttonen -Jérémy Leherpeur -Jérôme Petazzoni -Jörg Thalheim -K. Heller -Kai Blin -Kai Qiang Wu (Kennan) -Kamil Domański -Kamjar Gerami -Kanstantsin Shautsou -Kara Alexandra -Karan Lyons -Kareem Khazem -kargakis -Karl Grzeszczak -Karol Duleba -Karthik Karanth -Karthik Nayak -Kasper Fabæch Brandt -Kate Heddleston -Katie McLaughlin -Kato Kazuyoshi -Katrina Owen -Kawsar Saiyeed -Kay Yan -kayrus -Kazuhiro Sera -Ke Li -Ke Xu -Kei Ohmura -Keith Hudgins -Keli Hu -Ken Cochrane -Ken Herner -Ken ICHIKAWA -Ken Reese -Kenfe-Mickaël Laventure -Kenjiro Nakayama -Kent Johnson -Kenta Tada -Kevin "qwazerty" Houdebert -Kevin Burke -Kevin Clark -Kevin Feyrer -Kevin J. Lynagh -Kevin Jing Qiu -Kevin Kern -Kevin Menard -Kevin Meredith -Kevin P. Kucharczyk -Kevin Parsons -Kevin Richardson -Kevin Shi -Kevin Wallace -Kevin Yap -Keyvan Fatehi -kies -Kim BKC Carlbacker -Kim Eik -Kimbro Staken -Kir Kolyshkin -Kiran Gangadharan -Kirill SIbirev -knappe -Kohei Tsuruta -Koichi Shiraishi -Konrad Kleine -Konstantin Gribov -Konstantin L -Konstantin Pelykh -Krasi Georgiev -Krasimir Georgiev -Kris-Mikael Krister -Kristian Haugene -Kristina Zabunova -Krystian Wojcicki -Kun Zhang -Kunal Kushwaha -Kunal Tyagi -Kyle Conroy -Kyle Linden -Kyle Wuolle -kyu -Lachlan Coote -Lai Jiangshan -Lajos Papp -Lakshan Perera -Lalatendu Mohanty -Lance Chen -Lance Kinley -Lars Butler -Lars Kellogg-Stedman -Lars R. Damerow -Lars-Magnus Skog -Laszlo Meszaros -Laura Frank -Laurent Erignoux -Laurie Voss -Leandro Siqueira -Lee Chao <932819864@qq.com> -Lee, Meng-Han -leeplay -Lei Gong -Lei Jitang -Len Weincier -Lennie -Leo Gallucci -Leszek Kowalski -Levi Blackstone -Levi Gross -Lewis Daly -Lewis Marshall -Lewis Peckover -Li Yi -Liam Macgillavry -Liana Lo -Liang Mingqiang -Liang-Chi Hsieh -Liao Qingwei -Lifubang -Lihua Tang -Lily Guo -limsy -Lin Lu -LingFaKe -Linus Heckemann -Liran Tal -Liron Levin -Liu Bo -Liu Hua -liwenqi -lixiaobing10051267 -Liz Zhang -LIZAO LI -Lizzie Dixon <_@lizzie.io> -Lloyd Dewolf -Lokesh Mandvekar -longliqiang88 <394564827@qq.com> -Lorenz Leutgeb -Lorenzo Fontana -Lotus Fenn -Louis Delossantos -Louis Opter -Luca Favatella -Luca Marturana -Luca Orlandi -Luca-Bogdan Grigorescu -Lucas Chan -Lucas Chi -Lucas Molas -Lucas Silvestre -Luciano Mores -Luis Martínez de Bartolomé Izquierdo -Luiz Svoboda -Lukas Heeren -Lukas Waslowski -lukaspustina -Lukasz Zajaczkowski -Luke Marsden -Lyn -Lynda O'Leary -Lénaïc Huard -Ma Müller -Ma Shimiao -Mabin -Madhan Raj Mookkandy -Madhav Puri -Madhu Venugopal -Mageee -Mahesh Tiyyagura -malnick -Malte Janduda -Manfred Touron -Manfred Zabarauskas -Manjunath A Kumatagi -Mansi Nahar -Manuel Meurer -Manuel Rüger -Manuel Woelker -mapk0y -Marc Abramowitz -Marc Kuo -Marc Tamsky -Marcel Edmund Franke -Marcelo Horacio Fortino -Marcelo Salazar -Marco Hennings -Marcus Cobden -Marcus Farkas -Marcus Linke -Marcus Martins -Marcus Ramberg -Marek Goldmann -Marian Marinov -Marianna Tessel -Mario Loriedo -Marius Gundersen -Marius Sturm -Marius Voila -Mark Allen -Mark Jeromin -Mark McGranaghan -Mark McKinstry -Mark Milstein -Mark Oates -Mark Parker -Mark West -Markan Patel -Marko Mikulicic -Marko Tibold -Markus Fix -Markus Kortlang -Martijn Dwars -Martijn van Oosterhout -Martin Honermeyer -Martin Kelly -Martin Mosegaard Amdisen -Martin Muzatko -Martin Redmond -Mary Anthony -Masahito Zembutsu -Masato Ohba -Masayuki Morita -Mason Malone -Mateusz Sulima -Mathias Monnerville -Mathieu Champlon -Mathieu Le Marec - Pasquet -Mathieu Parent -Matt Apperson -Matt Bachmann -Matt Bentley -Matt Haggard -Matt Hoyle -Matt McCormick -Matt Moore -Matt Richardson -Matt Rickard -Matt Robenolt -Matt Schurenko -Matt Williams -Matthew Heon -Matthew Lapworth -Matthew Mayer -Matthew Mosesohn -Matthew Mueller -Matthew Riley -Matthias Klumpp -Matthias Kühnle -Matthias Rampke -Matthieu Hauglustaine -Mattias Jernberg -Mauricio Garavaglia -mauriyouth -Max Harmathy -Max Shytikov -Maxim Fedchyshyn -Maxim Ivanov -Maxim Kulkin -Maxim Treskin -Maxime Petazzoni -Maximiliano Maccanti -Maxwell -Meaglith Ma -meejah -Megan Kostick -Mehul Kar -Mei ChunTao -Mengdi Gao -Mert Yazıcıoğlu -mgniu -Micah Zoltu -Michael A. Smith -Michael Bridgen -Michael Brown -Michael Chiang -Michael Crosby -Michael Currie -Michael Friis -Michael Gorsuch -Michael Grauer -Michael Holzheu -Michael Hudson-Doyle -Michael Huettermann -Michael Irwin -Michael Käufl -Michael Neale -Michael Nussbaum -Michael Prokop -Michael Scharf -Michael Spetsiotis -Michael Stapelberg -Michael Steinert -Michael Thies -Michael West -Michael Zhao -Michal Fojtik -Michal Gebauer -Michal Jemala -Michal Minář -Michal Wieczorek -Michaël Pailloncy -Michał Czeraszkiewicz -Michał Gryko -Michiel de Jong -Mickaël Fortunato -Mickaël Remars -Miguel Angel Fernández -Miguel Morales -Mihai Borobocea -Mihuleacc Sergiu -Mike Brown -Mike Bush -Mike Casas -Mike Chelen -Mike Danese -Mike Dillon -Mike Dougherty -Mike Estes -Mike Gaffney -Mike Goelzer -Mike Leone -Mike Lundy -Mike MacCana -Mike Naberezny -Mike Snitzer -mikelinjie <294893458@qq.com> -Mikhail Sobolev -Miklos Szegedi -Milind Chawre -Miloslav Trmač -mingqing -Mingzhen Feng -Misty Stanley-Jones -Mitch Capper -Mizuki Urushida -mlarcher -Mohammad Banikazemi -Mohammad Nasirifar -Mohammed Aaqib Ansari -Mohit Soni -Moorthy RS -Morgan Bauer -Morgante Pell -Morgy93 -Morten Siebuhr -Morton Fox -Moysés Borges -mrfly -Mrunal Patel -Muayyad Alsadi -Mustafa Akın -Muthukumar R -Máximo Cuadros -Médi-Rémi Hashim -Nace Oroz -Nahum Shalman -Nakul Pathak -Nalin Dahyabhai -Nan Monnand Deng -Naoki Orii -Natalie Parker -Natanael Copa -Natasha Jarus -Nate Brennand -Nate Eagleson -Nate Jones -Nathan Hsieh -Nathan Kleyn -Nathan LeClaire -Nathan McCauley -Nathan Williams -Naveed Jamil -Neal McBurnett -Neil Horman -Neil Peterson -Nelson Chen -Neyazul Haque -Nghia Tran -Niall O'Higgins -Nicholas E. Rabenau -Nick Adcock -Nick DeCoursin -Nick Irvine -Nick Neisen -Nick Parker -Nick Payne -Nick Russo -Nick Stenning -Nick Stinemates -NickrenREN -Nicola Kabar -Nicolas Borboën -Nicolas De Loof -Nicolas Dudebout -Nicolas Goy -Nicolas Kaiser -Nicolas Sterchele -Nicolas V Castet -Nicolás Hock Isaza -Nigel Poulton -Nik Nyby -Nikhil Chawla -NikolaMandic -Nikolas Garofil -Nikolay Edigaryev -Nikolay Milovanov -Nirmal Mehta -Nishant Totla -NIWA Hideyuki -Noah Meyerhans -Noah Treuhaft -NobodyOnSE -noducks -Nolan Darilek -Noriki Nakamura -nponeccop -Nuutti Kotivuori -nzwsch -O.S. Tezer -objectified -Odin Ugedal -Oguz Bilgic -Oh Jinkyun -Ohad Schneider -ohmystack -Ole Reifschneider -Oliver Neal -Oliver Reason -Olivier Gambier -Olle Jonsson -Olli Janatuinen -Olly Pomeroy -Omri Shiv -Oriol Francès -Oskar Niburski -Otto Kekäläinen -Ouyang Liduo -Ovidio Mallo -Panagiotis Moustafellos -Paolo G. Giarrusso -Pascal -Pascal Bach -Pascal Borreli -Pascal Hartig -Patrick Böänziger -Patrick Devine -Patrick Hemmer -Patrick Stapleton -Patrik Cyvoct -pattichen -Paul -paul -Paul Annesley -Paul Bellamy -Paul Bowsher -Paul Furtado -Paul Hammond -Paul Jimenez -Paul Kehrer -Paul Lietar -Paul Liljenberg -Paul Morie -Paul Nasrat -Paul Weaver -Paulo Ribeiro -Pavel Lobashov -Pavel Matěja -Pavel Pletenev -Pavel Pospisil -Pavel Sutyrin -Pavel Tikhomirov -Pavlos Ratis -Pavol Vargovcik -Pawel Konczalski -Peeyush Gupta -Peggy Li -Pei Su -Peng Tao -Penghan Wang -Per Weijnitz -perhapszzy@sina.com -Peter Bourgon -Peter Braden -Peter Bücker -Peter Choi -Peter Dave Hello -Peter Edge -Peter Ericson -Peter Esbensen -Peter Jaffe -Peter Kang -Peter Malmgren -Peter Salvatore -Peter Volpe -Peter Waller -Petr Švihlík -Phil -Phil Estes -Phil Spitler -Philip Alexander Etling -Philip Monroe -Philipp Gillé -Philipp Wahala -Philipp Weissensteiner -Phillip Alexander -phineas -pidster -Piergiuliano Bossi -Pierre -Pierre Carrier -Pierre Dal-Pra -Pierre Wacrenier -Pierre-Alain RIVIERE -Piotr Bogdan -pixelistik -Porjo -Poul Kjeldager Sørensen -Pradeep Chhetri -Pradip Dhara -Prasanna Gautam -Pratik Karki -Prayag Verma -Priya Wadhwa -Projjol Banerji -Przemek Hejman -Pure White -pysqz -Qiang Huang -Qinglan Peng -qudongfang -Quentin Brossard -Quentin Perez -Quentin Tayssier -r0n22 -Radostin Stoyanov -Rafal Jeczalik -Rafe Colton -Raghavendra K T -Raghuram Devarakonda -Raja Sami -Rajat Pandit -Rajdeep Dua -Ralf Sippl -Ralle -Ralph Bean -Ramkumar Ramachandra -Ramon Brooker -Ramon van Alteren -RaviTeja Pothana -Ray Tsang -ReadmeCritic -Recursive Madman -Reficul -Regan McCooey -Remi Rampin -Remy Suen -Renato Riccieri Santos Zannon -Renaud Gaubert -Rhys Hiltner -Ri Xu -Ricardo N Feliciano -Rich Moyse -Rich Seymour -Richard -Richard Burnison -Richard Harvey -Richard Mathie -Richard Metzler -Richard Scothern -Richo Healey -Rick Bradley -Rick van de Loo -Rick Wieman -Rik Nijessen -Riku Voipio -Riley Guerin -Ritesh H Shukla -Riyaz Faizullabhoy -Rob Gulewich -Rob Vesse -Robert Bachmann -Robert Bittle -Robert Obryk -Robert Schneider -Robert Stern -Robert Terhaar -Robert Wallis -Robert Wang -Roberto G. Hashioka -Roberto Muñoz Fernández -Robin Naundorf -Robin Schneider -Robin Speekenbrink -Robin Thoni -robpc -Rodolfo Carvalho -Rodrigo Vaz -Roel Van Nyen -Roger Peppe -Rohit Jnagal -Rohit Kadam -Rohit Kapur -Rojin George -Roland Huß -Roland Kammerer -Roland Moriz -Roma Sokolov -Roman Dudin -Roman Mazur -Roman Strashkin -Ron Smits -Ron Williams -Rong Gao -Rong Zhang -Rongxiang Song -root -root -root -root -Rory Hunter -Rory McCune -Ross Boucher -Rovanion Luckey -Royce Remer -Rozhnov Alexandr -Rudolph Gottesheim -Rui Cao -Rui Lopes -Ruilin Li -Runshen Zhu -Russ Magee -Ryan Abrams -Ryan Anderson -Ryan Aslett -Ryan Belgrave -Ryan Detzel -Ryan Fowler -Ryan Liu -Ryan McLaughlin -Ryan O'Donnell -Ryan Seto -Ryan Simmen -Ryan Stelly -Ryan Thomas -Ryan Trauntvein -Ryan Wallner -Ryan Zhang -ryancooper7 -RyanDeng -Ryo Nakao -Rémy Greinhofer -s. rannou -s00318865 -Sabin Basyal -Sachin Joshi -Sagar Hani -Sainath Grandhi -Sakeven Jiang -Salahuddin Khan -Sally O'Malley -Sam Abed -Sam Alba -Sam Bailey -Sam J Sharpe -Sam Neirinck -Sam Reis -Sam Rijs -Sam Whited -Sambuddha Basu -Sami Wagiaalla -Samuel Andaya -Samuel Dion-Girardeau -Samuel Karp -Samuel PHAN -Sandeep Bansal -Sankar சங்கர் -Sanket Saurav -Santhosh Manohar -sapphiredev -Sargun Dhillon -Sascha Andres -Sascha Grunert -SataQiu -Satnam Singh -Satoshi Amemiya -Satoshi Tagomori -Scott Bessler -Scott Collier -Scott Johnston -Scott Stamp -Scott Walls -sdreyesg -Sean Christopherson -Sean Cronin -Sean Lee -Sean McIntyre -Sean OMeara -Sean P. Kane -Sean Rodman -Sebastiaan van Steenis -Sebastiaan van Stijn -Senthil Kumar Selvaraj -Senthil Kumaran -SeongJae Park -Seongyeol Lim -Serge Hallyn -Sergey Alekseev -Sergey Evstifeev -Sergii Kabashniuk -Sergio Lopez -Serhat Gülçiçek -SeungUkLee -Sevki Hasirci -Shane Canon -Shane da Silva -Shaun Kaasten -shaunol -Shawn Landden -Shawn Siefkas -shawnhe -Shayne Wang -Shekhar Gulati -Sheng Yang -Shengbo Song -Shev Yan -Shih-Yuan Lee -Shijiang Wei -Shijun Qin -Shishir Mahajan -Shoubhik Bose -Shourya Sarcar -Shu-Wai Chow -shuai-z -Shukui Yang -Shuwei Hao -Sian Lerk Lau -Sidhartha Mani -sidharthamani -Silas Sewell -Silvan Jegen -Simão Reis -Simei He -Simon Barendse -Simon Eskildsen -Simon Ferquel -Simon Leinen -Simon Menke -Simon Taranto -Simon Vikstrom -Sindhu S -Sjoerd Langkemper -skanehira -Solganik Alexander -Solomon Hykes -Song Gao -Soshi Katsuta -Soulou -Spencer Brown -Spencer Smith -Sridatta Thatipamala -Sridhar Ratnakumar -Srini Brahmaroutu -Srinivasan Srivatsan -Staf Wagemakers -Stanislav Bondarenko -Stanislav Levin -Steeve Morin -Stefan Berger -Stefan J. Wernli -Stefan Praszalowicz -Stefan S. -Stefan Scherer -Stefan Staudenmeyer -Stefan Weil -Stephan Spindler -Stephen Benjamin -Stephen Crosby -Stephen Day -Stephen Drake -Stephen Rust -Steve Desmond -Steve Dougherty -Steve Durrheimer -Steve Francia -Steve Koch -Steven Burgess -Steven Erenst -Steven Hartland -Steven Iveson -Steven Merrill -Steven Richards -Steven Taylor -Stig Larsson -Subhajit Ghosh -Sujith Haridasan -Sun Gengze <690388648@qq.com> -Sun Jianbo -Sune Keller -Sunny Gogoi -Suryakumar Sudar -Sven Dowideit -Swapnil Daingade -Sylvain Baubeau -Sylvain Bellemare -Sébastien -Sébastien HOUZÉ -Sébastien Luttringer -Sébastien Stormacq -Tabakhase -Tadej Janež -TAGOMORI Satoshi -tang0th -Tangi Colin -Tatsuki Sugiura -Tatsushi Inagaki -Taylan Isikdemir -Taylor Jones -Ted M. Young -Tehmasp Chaudhri -Tejaswini Duggaraju -Tejesh Mehta -terryding77 <550147740@qq.com> -tgic -Thatcher Peskens -theadactyl -Thell 'Bo' Fowler -Thermionix -Thijs Terlouw -Thomas Bikeev -Thomas Frössman -Thomas Gazagnaire -Thomas Grainger -Thomas Hansen -Thomas Leonard -Thomas Léveil -Thomas Orozco -Thomas Riccardi -Thomas Schroeter -Thomas Sjögren -Thomas Swift -Thomas Tanaka -Thomas Texier -Ti Zhou -Tianon Gravi -Tianyi Wang -Tibor Vass -Tiffany Jernigan -Tiffany Low -Till Wegmüller -Tim -Tim Bart -Tim Bosse -Tim Dettrick -Tim Düsterhus -Tim Hockin -Tim Potter -Tim Ruffles -Tim Smith -Tim Terhorst -Tim Wang -Tim Waugh -Tim Wraight -Tim Zju <21651152@zju.edu.cn> -timfeirg -Timothy Hobbs -tjwebb123 -tobe -Tobias Bieniek -Tobias Bradtke -Tobias Gesellchen -Tobias Klauser -Tobias Munk -Tobias Schmidt -Tobias Schwab -Todd Crane -Todd Lunter -Todd Whiteman -Toli Kuznets -Tom Barlow -Tom Booth -Tom Denham -Tom Fotherby -Tom Howe -Tom Hulihan -Tom Maaswinkel -Tom Sweeney -Tom Wilkie -Tom X. Tobin -Tomas Tomecek -Tomasz Kopczynski -Tomasz Lipinski -Tomasz Nurkiewicz -Tommaso Visconti -Tomáš Hrčka -Tonny Xu -Tony Abboud -Tony Daws -Tony Miller -toogley -Torstein Husebø -Tõnis Tiigi -Trace Andreason -tracylihui <793912329@qq.com> -Trapier Marshall -Travis Cline -Travis Thieman -Trent Ogren -Trevor -Trevor Pounds -Trevor Sullivan -Trishna Guha -Tristan Carel -Troy Denton -Tycho Andersen -Tyler Brock -Tyler Brown -Tzu-Jung Lee -uhayate -Ulysse Carion -Umesh Yadav -Utz Bacher -vagrant -Vaidas Jablonskis -vanderliang -Velko Ivanov -Veres Lajos -Victor Algaze -Victor Coisne -Victor Costan -Victor I. Wood -Victor Lyuboslavsky -Victor Marmol -Victor Palma -Victor Vieux -Victoria Bialas -Vijaya Kumar K -Vikram bir Singh -Viktor Stanchev -Viktor Vojnovski -VinayRaghavanKS -Vincent Batts -Vincent Bernat -Vincent Boulineau -Vincent Demeester -Vincent Giersch -Vincent Mayers -Vincent Woo -Vinod Kulkarni -Vishal Doshi -Vishnu Kannan -Vitaly Ostrosablin -Vitor Monteiro -Vivek Agarwal -Vivek Dasgupta -Vivek Goyal -Vladimir Bulyga -Vladimir Kirillov -Vladimir Pouzanov -Vladimir Rutsky -Vladimir Varankin -VladimirAus -Vlastimil Zeman -Vojtech Vitek (V-Teq) -waitingkuo -Walter Leibbrandt -Walter Stanish -Wang Chao -Wang Guoliang -Wang Jie -Wang Long -Wang Ping -Wang Xing -Wang Yuexiao -Wang Yumu <37442693@qq.com> -wanghuaiqing -Ward Vandewege -WarheadsSE -Wassim Dhif -Wayne Chang -Wayne Song -Weerasak Chongnguluam -Wei Fu -Wei Wu -Wei-Ting Kuo -weipeng -weiyan -Weiyang Zhu -Wen Cheng Ma -Wendel Fleming -Wenjun Tang -Wenkai Yin -wenlxie -Wentao Zhang -Wenxuan Zhao -Wenyu You <21551128@zju.edu.cn> -Wenzhi Liang -Wes Morgan -Wewang Xiaorenfine -Wiktor Kwapisiewicz -Will Dietz -Will Rouesnel -Will Weaver -willhf -William Delanoue -William Henry -William Hubbs -William Martin -William Riancho -William Thurston -Wilson Júnior -Wing-Kam Wong -WiseTrem -Wolfgang Powisch -Wonjun Kim -xamyzhao -Xian Chaobo -Xianglin Gao -Xianlu Bird -Xiao YongBiao -XiaoBing Jiang -Xiaodong Liu -Xiaodong Zhang -Xiaoxi He -Xiaoxu Chen -Xiaoyu Zhang -xichengliudui <1693291525@qq.com> -xiekeyang -Ximo Guanter Gonzálbez -Xinbo Weng -Xinfeng Liu -Xinzi Zhou -Xiuming Chen -Xuecong Liao -xuzhaokui -Yadnyawalkya Tale -Yahya -YAMADA Tsuyoshi -Yamasaki Masahide -Yan Feng -Yang Bai -Yang Pengfei -yangchenliang -Yanqiang Miao -Yao Zaiyong -Yash Murty -Yassine Tijani -Yasunori Mahata -Yazhong Liu -Yestin Sun -Yi EungJun -Yibai Zhang -Yihang Ho -Ying Li -Yohei Ueda -Yong Tang -Yongxin Li -Yongzhi Pan -Yosef Fertel -You-Sheng Yang (楊有勝) -youcai -Youcef YEKHLEF -Yu Changchun -Yu Chengxia -Yu Peng -Yu-Ju Hong -Yuan Sun -Yuanhong Peng -Yue Zhang -Yuhao Fang -Yuichiro Kaneko -Yunxiang Huang -Yurii Rashkovskii -Yusuf Tarık Günaydın -Yves Junqueira -Zac Dover -Zach Borboa -Zachary Jaffee -Zain Memon -Zaiste! -Zane DeGraffenried -Zefan Li -Zen Lin(Zhinan Lin) -Zhang Kun -Zhang Wei -Zhang Wentao -ZhangHang -zhangxianwei -Zhenan Ye <21551168@zju.edu.cn> -zhenghenghuo -Zhenhai Gao -Zhenkun Bi -zhipengzuo -Zhou Hao -Zhoulin Xie -Zhu Guihua -Zhu Kunjia -Zhuoyun Wei -Ziheng Liu -Zilin Du -zimbatm -Ziming Dong -ZJUshuaizhou <21551191@zju.edu.cn> -zmarouf -Zoltan Tombol -Zou Yu -zqh -Zuhayr Elahi -Zunayed Ali -Álex González -Álvaro Lázaro -Átila Camurça Alves -尹吉峰 -屈骏 -徐俊杰 -慕陶 -搏通 -黄艳红00139573 diff --git a/vendor/github.com/docker/docker/LICENSE b/vendor/github.com/docker/docker/LICENSE deleted file mode 100644 index 6d8d58fb676..00000000000 --- a/vendor/github.com/docker/docker/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 2013-2018 Docker, Inc. - - 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/docker/docker/NOTICE b/vendor/github.com/docker/docker/NOTICE deleted file mode 100644 index 58b19b6d15b..00000000000 --- a/vendor/github.com/docker/docker/NOTICE +++ /dev/null @@ -1,19 +0,0 @@ -Docker -Copyright 2012-2017 Docker, Inc. - -This product includes software developed at Docker, Inc. (https://www.docker.com). - -This product contains software (https://github.com/creack/pty) developed -by Keith Rarick, licensed under the MIT License. - -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/docker/docker/api/README.md b/vendor/github.com/docker/docker/api/README.md deleted file mode 100644 index f136c3433af..00000000000 --- a/vendor/github.com/docker/docker/api/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Working on the Engine API - -The Engine API is an HTTP API used by the command-line client to communicate with the daemon. It can also be used by third-party software to control the daemon. - -It consists of various components in this repository: - -- `api/swagger.yaml` A Swagger definition of the API. -- `api/types/` Types shared by both the client and server, representing various objects, options, responses, etc. Most are written manually, but some are automatically generated from the Swagger definition. See [#27919](https://github.com/docker/docker/issues/27919) for progress on this. -- `cli/` The command-line client. -- `client/` The Go client used by the command-line client. It can also be used by third-party Go programs. -- `daemon/` The daemon, which serves the API. - -## Swagger definition - -The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to: - -1. Automatically generate documentation. -2. Automatically generate the Go server and client. (A work-in-progress.) -3. Provide a machine readable version of the API for introspecting what it can do, automatically generating clients for other languages, etc. - -## Updating the API documentation - -The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, edit this file to represent the change in the documentation. - -The file is split into two main sections: - -- `definitions`, which defines re-usable objects used in requests and responses -- `paths`, which defines the API endpoints (and some inline objects which don't need to be reusable) - -To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section. - -There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919). - -`swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful when making edits to ensure you are doing the right thing. - -## Viewing the API documentation - -When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly. - -Run `make swagger-docs` and a preview will be running at `http://localhost`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation. - -The production documentation is generated by vendoring `swagger.yaml` into [docker/docker.github.io](https://github.com/docker/docker.github.io). diff --git a/vendor/github.com/docker/docker/api/common.go b/vendor/github.com/docker/docker/api/common.go deleted file mode 100644 index 1565e2af647..00000000000 --- a/vendor/github.com/docker/docker/api/common.go +++ /dev/null @@ -1,11 +0,0 @@ -package api // import "github.com/docker/docker/api" - -// Common constants for daemon and client. -const ( - // DefaultVersion of Current REST API - DefaultVersion = "1.41" - - // NoBaseImageSpecifier is the symbol used by the FROM - // command to specify that no base image is to be used. - NoBaseImageSpecifier = "scratch" -) diff --git a/vendor/github.com/docker/docker/api/common_unix.go b/vendor/github.com/docker/docker/api/common_unix.go deleted file mode 100644 index 504b0c90d7b..00000000000 --- a/vendor/github.com/docker/docker/api/common_unix.go +++ /dev/null @@ -1,6 +0,0 @@ -// +build !windows - -package api // import "github.com/docker/docker/api" - -// MinVersion represents Minimum REST API version supported -const MinVersion = "1.12" diff --git a/vendor/github.com/docker/docker/api/common_windows.go b/vendor/github.com/docker/docker/api/common_windows.go deleted file mode 100644 index 590ba5479be..00000000000 --- a/vendor/github.com/docker/docker/api/common_windows.go +++ /dev/null @@ -1,8 +0,0 @@ -package api // import "github.com/docker/docker/api" - -// MinVersion represents Minimum REST API version supported -// Technically the first daemon API version released on Windows is v1.25 in -// engine version 1.13. However, some clients are explicitly using downlevel -// APIs (e.g. docker-compose v2.1 file format) and that is just too restrictive. -// Hence also allowing 1.24 on Windows. -const MinVersion string = "1.24" diff --git a/vendor/github.com/docker/docker/api/swagger-gen.yaml b/vendor/github.com/docker/docker/api/swagger-gen.yaml deleted file mode 100644 index f07a02737f7..00000000000 --- a/vendor/github.com/docker/docker/api/swagger-gen.yaml +++ /dev/null @@ -1,12 +0,0 @@ - -layout: - models: - - name: definition - source: asset:model - target: "{{ joinFilePath .Target .ModelPackage }}" - file_name: "{{ (snakize (pascalize .Name)) }}.go" - operations: - - name: handler - source: asset:serverOperation - target: "{{ joinFilePath .Target .APIPackage .Package }}" - file_name: "{{ (snakize (pascalize .Name)) }}.go" diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml deleted file mode 100644 index 1294e5a22cf..00000000000 --- a/vendor/github.com/docker/docker/api/swagger.yaml +++ /dev/null @@ -1,11425 +0,0 @@ -# A Swagger 2.0 (a.k.a. OpenAPI) definition of the Engine API. -# -# This is used for generating API documentation and the types used by the -# client/server. See api/README.md for more information. -# -# Some style notes: -# - This file is used by ReDoc, which allows GitHub Flavored Markdown in -# descriptions. -# - There is no maximum line length, for ease of editing and pretty diffs. -# - operationIds are in the format "NounVerb", with a singular noun. - -swagger: "2.0" -schemes: - - "http" - - "https" -produces: - - "application/json" - - "text/plain" -consumes: - - "application/json" - - "text/plain" -basePath: "/v1.41" -info: - title: "Docker Engine API" - version: "1.41" - x-logo: - url: "https://docs.docker.com/images/logo-docker-main.png" - description: | - The Engine API is an HTTP API served by Docker Engine. It is the API the - Docker client uses to communicate with the Engine, so everything the Docker - client can do can be done with the API. - - Most of the client's commands map directly to API endpoints (e.g. `docker ps` - is `GET /containers/json`). The notable exception is running containers, - which consists of several API calls. - - # Errors - - The API uses standard HTTP status codes to indicate the success or failure - of the API call. The body of the response will be JSON in the following - format: - - ``` - { - "message": "page not found" - } - ``` - - # Versioning - - The API is usually changed in each release, so API calls are versioned to - ensure that clients don't break. To lock to a specific version of the API, - you prefix the URL with its version, for example, call `/v1.30/info` to use - the v1.30 version of the `/info` endpoint. If the API version specified in - 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.41) is used. - For example, calling `/info` is the same as calling `/v1.41/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 - 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 - daemons. - - - # Authentication - - Authentication for registries is handled client side. The client has to send - authentication details to various endpoints that need to communicate with - registries, such as `POST /images/(name)/push`. These are sent as - `X-Registry-Auth` header as a [base64url encoded](https://tools.ietf.org/html/rfc4648#section-5) - (JSON) string with the following structure: - - ``` - { - "username": "string", - "password": "string", - "email": "string", - "serveraddress": "string" - } - ``` - - The `serveraddress` is a domain/IP without a protocol. Throughout this - structure, double quotes are required. - - If you have already got an identity token from the [`/auth` endpoint](#operation/SystemAuth), - you can just pass this instead of credentials: - - ``` - { - "identitytoken": "9cbaf023786cd7..." - } - ``` - -# The tags on paths define the menu sections in the ReDoc documentation, so -# the usage of tags must make sense for that: -# - They should be singular, not plural. -# - There should not be too many tags, or the menu becomes unwieldy. For -# example, it is preferable to add a path to the "System" tag instead of -# creating a tag with a single path in it. -# - The order of tags in this list defines the order in the menu. -tags: - # Primary objects - - name: "Container" - x-displayName: "Containers" - description: | - Create and manage containers. - - name: "Image" - x-displayName: "Images" - - name: "Network" - x-displayName: "Networks" - description: | - Networks are user-defined networks that containers can be attached to. - See the [networking documentation](https://docs.docker.com/network/) - for more information. - - name: "Volume" - x-displayName: "Volumes" - description: | - Create and manage persistent storage that can be attached to containers. - - name: "Exec" - x-displayName: "Exec" - description: | - Run new commands inside running containers. Refer to the - [command-line reference](https://docs.docker.com/engine/reference/commandline/exec/) - for more information. - - To exec a command in a container, you first need to create an exec instance, - then start it. These two API endpoints are wrapped up in a single command-line - command, `docker exec`. - - # Swarm things - - name: "Swarm" - x-displayName: "Swarm" - description: | - Engines can be clustered together in a swarm. Refer to the - [swarm mode documentation](https://docs.docker.com/engine/swarm/) - for more information. - - name: "Node" - x-displayName: "Nodes" - description: | - Nodes are instances of the Engine participating in a swarm. Swarm mode - must be enabled for these endpoints to work. - - name: "Service" - x-displayName: "Services" - description: | - Services are the definitions of tasks to run on a swarm. Swarm mode must - be enabled for these endpoints to work. - - name: "Task" - x-displayName: "Tasks" - description: | - A task is a container running on a swarm. It is the atomic scheduling unit - of swarm. Swarm mode must be enabled for these endpoints to work. - - name: "Secret" - x-displayName: "Secrets" - description: | - Secrets are sensitive data that can be used by services. Swarm mode must - be enabled for these endpoints to work. - - name: "Config" - x-displayName: "Configs" - description: | - Configs are application configurations that can be used by services. Swarm - mode must be enabled for these endpoints to work. - # System things - - name: "Plugin" - x-displayName: "Plugins" - - name: "System" - x-displayName: "System" - -definitions: - Port: - type: "object" - description: "An open port on a container" - required: [PrivatePort, Type] - properties: - IP: - type: "string" - format: "ip-address" - description: "Host IP address that the container's port is mapped to" - PrivatePort: - type: "integer" - format: "uint16" - x-nullable: false - description: "Port on the container" - PublicPort: - type: "integer" - format: "uint16" - description: "Port exposed on the host" - Type: - type: "string" - x-nullable: false - enum: ["tcp", "udp", "sctp"] - example: - PrivatePort: 8080 - PublicPort: 80 - Type: "tcp" - - MountPoint: - type: "object" - description: "A mount point inside a container" - properties: - Type: - type: "string" - Name: - type: "string" - Source: - type: "string" - Destination: - type: "string" - Driver: - type: "string" - Mode: - type: "string" - RW: - type: "boolean" - Propagation: - type: "string" - - DeviceMapping: - type: "object" - description: "A device mapping between the host and container" - properties: - PathOnHost: - type: "string" - PathInContainer: - type: "string" - CgroupPermissions: - type: "string" - example: - PathOnHost: "/dev/deviceName" - PathInContainer: "/dev/deviceName" - CgroupPermissions: "mrw" - - DeviceRequest: - type: "object" - description: "A request for devices to be sent to device drivers" - properties: - Driver: - type: "string" - example: "nvidia" - Count: - type: "integer" - example: -1 - DeviceIDs: - type: "array" - items: - type: "string" - example: - - "0" - - "1" - - "GPU-fef8089b-4820-abfc-e83e-94318197576e" - Capabilities: - description: | - A list of capabilities; an OR list of AND lists of capabilities. - type: "array" - items: - type: "array" - items: - type: "string" - example: - # gpu AND nvidia AND compute - - ["gpu", "nvidia", "compute"] - Options: - description: | - Driver-specific options, specified as a key/value pairs. These options - are passed directly to the driver. - type: "object" - additionalProperties: - type: "string" - - ThrottleDevice: - type: "object" - properties: - Path: - description: "Device path" - type: "string" - Rate: - description: "Rate" - type: "integer" - format: "int64" - minimum: 0 - - Mount: - type: "object" - properties: - Target: - description: "Container path." - type: "string" - Source: - description: "Mount source (e.g. a volume name, a host path)." - type: "string" - Type: - description: | - The mount type. Available types: - - - `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. - - `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. - type: "string" - enum: - - "bind" - - "volume" - - "tmpfs" - - "npipe" - ReadOnly: - description: "Whether the mount should be read-only." - type: "boolean" - Consistency: - description: "The consistency requirement for the mount: `default`, `consistent`, `cached`, or `delegated`." - type: "string" - BindOptions: - description: "Optional configuration for the `bind` type." - type: "object" - properties: - Propagation: - description: "A propagation mode with the value `[r]private`, `[r]shared`, or `[r]slave`." - type: "string" - enum: - - "private" - - "rprivate" - - "shared" - - "rshared" - - "slave" - - "rslave" - NonRecursive: - description: "Disable recursive bind mount." - type: "boolean" - default: false - VolumeOptions: - description: "Optional configuration for the `volume` type." - type: "object" - properties: - NoCopy: - description: "Populate volume with data from the target." - type: "boolean" - default: false - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - DriverConfig: - description: "Map of driver specific options" - type: "object" - properties: - Name: - description: "Name of the driver to use to create the volume." - type: "string" - Options: - description: "key/value map of driver specific options." - type: "object" - additionalProperties: - type: "string" - TmpfsOptions: - description: "Optional configuration for the `tmpfs` type." - type: "object" - properties: - SizeBytes: - description: "The size for the tmpfs mount in bytes." - type: "integer" - format: "int64" - Mode: - description: "The permission mode for the tmpfs mount in an integer." - type: "integer" - - RestartPolicy: - description: | - The behavior to apply when the container exits. The default is not to - restart. - - An ever increasing delay (double the previous delay, starting at 100ms) is - added before each restart to prevent flooding the server. - type: "object" - properties: - Name: - type: "string" - description: | - - Empty string means not to restart - - `always` Always restart - - `unless-stopped` Restart always except when the user has manually stopped the container - - `on-failure` Restart only when the container exit code is non-zero - enum: - - "" - - "always" - - "unless-stopped" - - "on-failure" - MaximumRetryCount: - type: "integer" - description: | - If `on-failure` is used, the number of times to retry before giving up. - - Resources: - description: "A container's resources (cgroups config, ulimits, etc)" - type: "object" - properties: - # Applicable to all platforms - CpuShares: - description: | - An integer value representing this container's relative CPU weight - versus other containers. - type: "integer" - Memory: - description: "Memory limit in bytes." - type: "integer" - format: "int64" - default: 0 - # Applicable to UNIX platforms - CgroupParent: - description: | - Path to `cgroups` under which the container's `cgroup` is created. If - the path is not absolute, the path is considered to be relative to the - `cgroups` path of the init process. Cgroups are created if they do not - already exist. - type: "string" - BlkioWeight: - description: "Block IO weight (relative weight)." - type: "integer" - minimum: 0 - maximum: 1000 - BlkioWeightDevice: - description: | - Block IO weight (relative device weight) in the form: - - ``` - [{"Path": "device_path", "Weight": weight}] - ``` - type: "array" - items: - type: "object" - properties: - Path: - type: "string" - Weight: - type: "integer" - minimum: 0 - BlkioDeviceReadBps: - description: | - Limit read rate (bytes per second) from a device, in the form: - - ``` - [{"Path": "device_path", "Rate": rate}] - ``` - type: "array" - items: - $ref: "#/definitions/ThrottleDevice" - BlkioDeviceWriteBps: - description: | - Limit write rate (bytes per second) to a device, in the form: - - ``` - [{"Path": "device_path", "Rate": rate}] - ``` - type: "array" - items: - $ref: "#/definitions/ThrottleDevice" - BlkioDeviceReadIOps: - description: | - Limit read rate (IO per second) from a device, in the form: - - ``` - [{"Path": "device_path", "Rate": rate}] - ``` - type: "array" - items: - $ref: "#/definitions/ThrottleDevice" - BlkioDeviceWriteIOps: - description: | - Limit write rate (IO per second) to a device, in the form: - - ``` - [{"Path": "device_path", "Rate": rate}] - ``` - type: "array" - items: - $ref: "#/definitions/ThrottleDevice" - CpuPeriod: - description: "The length of a CPU period in microseconds." - type: "integer" - format: "int64" - CpuQuota: - description: | - Microseconds of CPU time that the container can get in a CPU period. - type: "integer" - format: "int64" - CpuRealtimePeriod: - description: | - The length of a CPU real-time period in microseconds. Set to 0 to - allocate no time allocated to real-time tasks. - type: "integer" - format: "int64" - CpuRealtimeRuntime: - description: | - The length of a CPU real-time runtime in microseconds. Set to 0 to - allocate no time allocated to real-time tasks. - type: "integer" - format: "int64" - CpusetCpus: - description: | - CPUs in which to allow execution (e.g., `0-3`, `0,1`). - type: "string" - example: "0-3" - CpusetMems: - description: | - Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only - effective on NUMA systems. - type: "string" - Devices: - description: "A list of devices to add to the container." - type: "array" - items: - $ref: "#/definitions/DeviceMapping" - DeviceCgroupRules: - description: "a list of cgroup rules to apply to the container" - type: "array" - items: - type: "string" - example: "c 13:* rwm" - DeviceRequests: - description: | - A list of requests for devices to be sent to device drivers. - type: "array" - items: - $ref: "#/definitions/DeviceRequest" - KernelMemory: - description: | - Kernel memory limit in bytes. - -


- - > **Deprecated**: This field is deprecated as the kernel 5.4 deprecated - > `kmem.limit_in_bytes`. - type: "integer" - format: "int64" - example: 209715200 - KernelMemoryTCP: - description: "Hard limit for kernel TCP buffer memory (in bytes)." - type: "integer" - format: "int64" - MemoryReservation: - description: "Memory soft limit in bytes." - type: "integer" - format: "int64" - MemorySwap: - description: | - Total memory limit (memory + swap). Set as `-1` to enable unlimited - swap. - type: "integer" - format: "int64" - MemorySwappiness: - description: | - Tune a container's memory swappiness behavior. Accepts an integer - between 0 and 100. - type: "integer" - format: "int64" - minimum: 0 - maximum: 100 - NanoCpus: - description: "CPU quota in units of 10-9 CPUs." - type: "integer" - format: "int64" - OomKillDisable: - description: "Disable OOM Killer for the container." - type: "boolean" - Init: - description: | - Run an init inside the container that forwards signals and reaps - processes. This field is omitted if empty, and the default (as - configured on the daemon) is used. - type: "boolean" - x-nullable: true - PidsLimit: - description: | - Tune a container's PIDs limit. Set `0` or `-1` for unlimited, or `null` - to not change. - type: "integer" - format: "int64" - x-nullable: true - Ulimits: - description: | - A list of resource limits to set in the container. For example: - - ``` - {"Name": "nofile", "Soft": 1024, "Hard": 2048} - ``` - type: "array" - items: - type: "object" - properties: - Name: - description: "Name of ulimit" - type: "string" - Soft: - description: "Soft limit" - type: "integer" - Hard: - description: "Hard limit" - type: "integer" - # Applicable to Windows - CpuCount: - description: | - The number of usable CPUs (Windows only). - - On Windows Server containers, the processor resource controls are - mutually exclusive. The order of precedence is `CPUCount` first, then - `CPUShares`, and `CPUPercent` last. - type: "integer" - format: "int64" - CpuPercent: - description: | - The usable percentage of the available CPUs (Windows only). - - On Windows Server containers, the processor resource controls are - mutually exclusive. The order of precedence is `CPUCount` first, then - `CPUShares`, and `CPUPercent` last. - type: "integer" - format: "int64" - IOMaximumIOps: - description: "Maximum IOps for the container system drive (Windows only)" - type: "integer" - format: "int64" - IOMaximumBandwidth: - description: | - Maximum IO in bytes per second for the container system drive - (Windows only). - type: "integer" - format: "int64" - - Limit: - description: | - An object describing a limit on resources which can be requested by a task. - type: "object" - properties: - NanoCPUs: - type: "integer" - format: "int64" - example: 4000000000 - MemoryBytes: - type: "integer" - format: "int64" - example: 8272408576 - Pids: - description: | - Limits the maximum number of PIDs in the container. Set `0` for unlimited. - type: "integer" - format: "int64" - default: 0 - example: 100 - - ResourceObject: - description: | - An object describing the resources which can be advertised by a node and - requested by a task. - type: "object" - properties: - NanoCPUs: - type: "integer" - format: "int64" - example: 4000000000 - MemoryBytes: - type: "integer" - format: "int64" - example: 8272408576 - GenericResources: - $ref: "#/definitions/GenericResources" - - GenericResources: - description: | - User-defined resources can be either Integer resources (e.g, `SSD=3`) or - String resources (e.g, `GPU=UUID1`). - type: "array" - items: - type: "object" - properties: - NamedResourceSpec: - type: "object" - properties: - Kind: - type: "string" - Value: - type: "string" - DiscreteResourceSpec: - type: "object" - properties: - Kind: - type: "string" - Value: - type: "integer" - format: "int64" - example: - - DiscreteResourceSpec: - Kind: "SSD" - Value: 3 - - NamedResourceSpec: - Kind: "GPU" - Value: "UUID1" - - NamedResourceSpec: - Kind: "GPU" - Value: "UUID2" - - HealthConfig: - description: "A test to perform to check that the container is healthy." - type: "object" - properties: - Test: - description: | - The test to perform. Possible values are: - - - `[]` inherit healthcheck from image or parent image - - `["NONE"]` disable healthcheck - - `["CMD", args...]` exec arguments directly - - `["CMD-SHELL", command]` run command with system's default shell - type: "array" - items: - type: "string" - Interval: - description: | - The time to wait between checks in nanoseconds. It should be 0 or at - least 1000000 (1 ms). 0 means inherit. - type: "integer" - Timeout: - description: | - The time to wait before considering the check to have hung. It should - be 0 or at least 1000000 (1 ms). 0 means inherit. - type: "integer" - Retries: - description: | - The number of consecutive failures needed to consider a container as - unhealthy. 0 means inherit. - type: "integer" - StartPeriod: - description: | - Start period for the container to initialize before starting - health-retries countdown in nanoseconds. It should be 0 or at least - 1000000 (1 ms). 0 means inherit. - type: "integer" - - Health: - description: | - Health stores information about the container's healthcheck results. - type: "object" - properties: - Status: - description: | - Status is one of `none`, `starting`, `healthy` or `unhealthy` - - - "none" Indicates there is no healthcheck - - "starting" Starting indicates that the container is not yet ready - - "healthy" Healthy indicates that the container is running correctly - - "unhealthy" Unhealthy indicates that the container has a problem - type: "string" - enum: - - "none" - - "starting" - - "healthy" - - "unhealthy" - example: "healthy" - FailingStreak: - description: "FailingStreak is the number of consecutive failures" - type: "integer" - example: 0 - Log: - type: "array" - description: | - Log contains the last few results (oldest first) - items: - x-nullable: true - $ref: "#/definitions/HealthcheckResult" - - HealthcheckResult: - description: | - HealthcheckResult stores information about a single run of a healthcheck probe - type: "object" - properties: - Start: - description: | - Date and time at which this check started in - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. - type: "string" - format: "date-time" - example: "2020-01-04T10:44:24.496525531Z" - End: - description: | - Date and time at which this check ended in - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. - type: "string" - format: "dateTime" - example: "2020-01-04T10:45:21.364524523Z" - ExitCode: - description: | - ExitCode meanings: - - - `0` healthy - - `1` unhealthy - - `2` reserved (considered unhealthy) - - other values: error running probe - type: "integer" - example: 0 - Output: - description: "Output from last check" - type: "string" - - HostConfig: - description: "Container configuration that depends on the host we are running on" - allOf: - - $ref: "#/definitions/Resources" - - type: "object" - properties: - # Applicable to all platforms - Binds: - type: "array" - description: | - A list of volume bindings for this container. Each volume binding - is a string in one of these forms: - - - `host-src:container-dest[:options]` to bind-mount a host path - into the container. Both `host-src`, and `container-dest` must - be an _absolute_ path. - - `volume-name:container-dest[:options]` to bind-mount a volume - managed by a volume driver into the container. `container-dest` - must be an _absolute_ path. - - `options` is an optional, comma-delimited list of: - - - `nocopy` disables automatic copying of data from the container - path to the volume. The `nocopy` flag only applies to named volumes. - - `[ro|rw]` mounts a volume read-only or read-write, respectively. - If omitted or set to `rw`, volumes are mounted read-write. - - `[z|Z]` applies SELinux labels to allow or deny multiple containers - to read and write to the same volume. - - `z`: a _shared_ content label is applied to the content. This - label indicates that multiple containers can share the volume - content, for both reading and writing. - - `Z`: a _private unshared_ label is applied to the content. - This label indicates that only the current container can use - a private volume. Labeling systems such as SELinux require - proper labels to be placed on volume content that is mounted - into a container. Without a label, the security system can - prevent a container's processes from using the content. By - default, the labels set by the host operating system are not - modified. - - `[[r]shared|[r]slave|[r]private]` specifies mount - [propagation behavior](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt). - This only applies to bind-mounted volumes, not internal volumes - or named volumes. Mount propagation requires the source mount - point (the location where the source directory is mounted in the - host operating system) to have the correct propagation properties. - For shared volumes, the source mount point must be set to `shared`. - For slave volumes, the mount must be set to either `shared` or - `slave`. - items: - type: "string" - ContainerIDFile: - type: "string" - description: "Path to a file where the container ID is written" - LogConfig: - type: "object" - description: "The logging configuration for this container" - properties: - Type: - type: "string" - enum: - - "json-file" - - "syslog" - - "journald" - - "gelf" - - "fluentd" - - "awslogs" - - "splunk" - - "etwlogs" - - "none" - Config: - type: "object" - additionalProperties: - type: "string" - NetworkMode: - type: "string" - description: | - Network mode to use for this container. Supported standard values - are: `bridge`, `host`, `none`, and `container:`. Any - other value is taken as a custom network's name to which this - container should connect to. - PortBindings: - $ref: "#/definitions/PortMap" - RestartPolicy: - $ref: "#/definitions/RestartPolicy" - AutoRemove: - type: "boolean" - description: | - Automatically remove the container when the container's process - exits. This has no effect if `RestartPolicy` is set. - VolumeDriver: - type: "string" - description: "Driver that this container uses to mount volumes." - VolumesFrom: - type: "array" - description: | - A list of volumes to inherit from another container, specified in - the form `[:]`. - items: - type: "string" - Mounts: - description: | - Specification for mounts to be added to the container. - type: "array" - items: - $ref: "#/definitions/Mount" - - # Applicable to UNIX platforms - CapAdd: - type: "array" - description: | - A list of kernel capabilities to add to the container. Conflicts - with option 'Capabilities'. - items: - type: "string" - CapDrop: - type: "array" - description: | - A list of kernel capabilities to drop from the container. Conflicts - with option 'Capabilities'. - items: - type: "string" - CgroupnsMode: - type: "string" - enum: - - "private" - - "host" - description: | - cgroup namespace mode for the container. Possible values are: - - - `"private"`: the container runs in its own private cgroup namespace - - `"host"`: use the host system's cgroup namespace - - If not specified, the daemon default is used, which can either be `"private"` - or `"host"`, depending on daemon version, kernel support and configuration. - Dns: - type: "array" - description: "A list of DNS servers for the container to use." - items: - type: "string" - DnsOptions: - type: "array" - description: "A list of DNS options." - items: - type: "string" - DnsSearch: - type: "array" - description: "A list of DNS search domains." - items: - type: "string" - ExtraHosts: - type: "array" - description: | - A list of hostnames/IP mappings to add to the container's `/etc/hosts` - file. Specified in the form `["hostname:IP"]`. - items: - type: "string" - GroupAdd: - type: "array" - description: | - A list of additional groups that the container process will run as. - items: - type: "string" - IpcMode: - type: "string" - description: | - IPC sharing mode for the container. Possible values are: - - - `"none"`: own private IPC namespace, with /dev/shm not mounted - - `"private"`: own private IPC namespace - - `"shareable"`: own private IPC namespace, with a possibility to share it with other containers - - `"container:"`: join another (shareable) container's IPC namespace - - `"host"`: use the host system's IPC namespace - - If not specified, daemon default is used, which can either be `"private"` - or `"shareable"`, depending on daemon version and configuration. - Cgroup: - type: "string" - description: "Cgroup to use for the container." - Links: - type: "array" - description: | - A list of links for the container in the form `container_name:alias`. - items: - type: "string" - OomScoreAdj: - type: "integer" - description: | - An integer value containing the score given to the container in - order to tune OOM killer preferences. - example: 500 - PidMode: - type: "string" - description: | - Set the PID (Process) Namespace mode for the container. It can be - either: - - - `"container:"`: joins another container's PID namespace - - `"host"`: use the host's PID namespace inside the container - Privileged: - type: "boolean" - description: "Gives the container full access to the host." - PublishAllPorts: - type: "boolean" - description: | - Allocates an ephemeral host port for all of a container's - exposed ports. - - Ports are de-allocated when the container stops and allocated when - the container starts. The allocated port might be changed when - restarting the container. - - The port is selected from the ephemeral port range that depends on - the kernel. For example, on Linux the range is defined by - `/proc/sys/net/ipv4/ip_local_port_range`. - ReadonlyRootfs: - type: "boolean" - description: "Mount the container's root filesystem as read only." - SecurityOpt: - type: "array" - description: "A list of string values to customize labels for MLS - systems, such as SELinux." - items: - type: "string" - StorageOpt: - type: "object" - description: | - Storage driver options for this container, in the form `{"size": "120G"}`. - additionalProperties: - type: "string" - Tmpfs: - type: "object" - description: | - A map of container directories which should be replaced by tmpfs - mounts, and their corresponding mount options. For example: - - ``` - { "/run": "rw,noexec,nosuid,size=65536k" } - ``` - additionalProperties: - type: "string" - UTSMode: - type: "string" - description: "UTS namespace to use for the container." - UsernsMode: - type: "string" - description: | - Sets the usernamespace mode for the container when usernamespace - remapping option is enabled. - ShmSize: - type: "integer" - description: | - Size of `/dev/shm` in bytes. If omitted, the system uses 64MB. - minimum: 0 - Sysctls: - type: "object" - description: | - A list of kernel parameters (sysctls) to set in the container. - For example: - - ``` - {"net.ipv4.ip_forward": "1"} - ``` - additionalProperties: - type: "string" - Runtime: - type: "string" - description: "Runtime to use with this container." - # Applicable to Windows - ConsoleSize: - type: "array" - description: | - Initial console size, as an `[height, width]` array. (Windows only) - minItems: 2 - maxItems: 2 - items: - type: "integer" - minimum: 0 - Isolation: - type: "string" - description: | - Isolation technology of the container. (Windows only) - enum: - - "default" - - "process" - - "hyperv" - MaskedPaths: - type: "array" - description: | - The list of paths to be masked inside the container (this overrides - the default set of paths). - items: - type: "string" - ReadonlyPaths: - type: "array" - description: | - The list of paths to be set as read-only inside the container - (this overrides the default set of paths). - items: - type: "string" - - ContainerConfig: - description: "Configuration for a container that is portable between hosts" - type: "object" - properties: - Hostname: - description: "The hostname to use for the container, as a valid RFC 1123 hostname." - type: "string" - Domainname: - description: "The domain name to use for the container." - type: "string" - User: - description: "The user that commands are run as inside the container." - type: "string" - AttachStdin: - description: "Whether to attach to `stdin`." - type: "boolean" - default: false - AttachStdout: - description: "Whether to attach to `stdout`." - type: "boolean" - default: true - AttachStderr: - description: "Whether to attach to `stderr`." - type: "boolean" - default: true - ExposedPorts: - description: | - An object mapping ports to an empty object in the form: - - `{"/": {}}` - type: "object" - additionalProperties: - type: "object" - enum: - - {} - default: {} - Tty: - description: | - Attach standard streams to a TTY, including `stdin` if it is not closed. - type: "boolean" - default: false - OpenStdin: - description: "Open `stdin`" - type: "boolean" - default: false - StdinOnce: - description: "Close `stdin` after one attached client disconnects" - type: "boolean" - default: false - Env: - description: | - A list of environment variables to set inside the container in the - form `["VAR=value", ...]`. A variable without `=` is removed from the - environment, rather than to have an empty value. - type: "array" - items: - type: "string" - Cmd: - description: | - Command to run specified as a string or an array of strings. - type: "array" - items: - type: "string" - Healthcheck: - $ref: "#/definitions/HealthConfig" - ArgsEscaped: - description: "Command is already escaped (Windows only)" - type: "boolean" - Image: - description: | - The name of the image to use when creating the container/ - type: "string" - Volumes: - description: | - An object mapping mount point paths inside the container to empty - objects. - type: "object" - additionalProperties: - type: "object" - enum: - - {} - default: {} - WorkingDir: - description: "The working directory for commands to run in." - type: "string" - Entrypoint: - description: | - The entry point for the container as a string or an array of strings. - - If the array consists of exactly one empty string (`[""]`) then the - entry point is reset to system default (i.e., the entry point used by - docker when there is no `ENTRYPOINT` instruction in the `Dockerfile`). - type: "array" - items: - type: "string" - NetworkDisabled: - description: "Disable networking for the container." - type: "boolean" - MacAddress: - description: "MAC address of the container." - type: "string" - OnBuild: - description: | - `ONBUILD` metadata that were defined in the image's `Dockerfile`. - type: "array" - items: - type: "string" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - StopSignal: - description: | - Signal to stop a container as a string or unsigned integer. - type: "string" - default: "SIGTERM" - StopTimeout: - description: "Timeout to stop a container in seconds." - type: "integer" - default: 10 - Shell: - description: | - Shell for when `RUN`, `CMD`, and `ENTRYPOINT` uses a shell. - type: "array" - items: - type: "string" - - NetworkingConfig: - description: | - NetworkingConfig represents the container's networking configuration for - each of its interfaces. - It is used for the networking configs specified in the `docker create` - and `docker network connect` commands. - type: "object" - properties: - EndpointsConfig: - description: | - A mapping of network name to endpoint configuration for that network. - type: "object" - additionalProperties: - $ref: "#/definitions/EndpointSettings" - example: - # putting an example here, instead of using the example values from - # /definitions/EndpointSettings, because containers/create currently - # does not support attaching to multiple networks, so the example request - # would be confusing if it showed that multiple networks can be contained - # in the EndpointsConfig. - # TODO remove once we support multiple networks on container create (see https://github.com/moby/moby/blob/07e6b843594e061f82baa5fa23c2ff7d536c2a05/daemon/create.go#L323) - EndpointsConfig: - isolated_nw: - IPAMConfig: - IPv4Address: "172.20.30.33" - IPv6Address: "2001:db8:abcd::3033" - LinkLocalIPs: - - "169.254.34.68" - - "fe80::3468" - Links: - - "container_1" - - "container_2" - Aliases: - - "server_x" - - "server_y" - - NetworkSettings: - description: "NetworkSettings exposes the network settings in the API" - type: "object" - properties: - Bridge: - description: Name of the network'a bridge (for example, `docker0`). - type: "string" - example: "docker0" - SandboxID: - description: SandboxID uniquely represents a container's network stack. - type: "string" - example: "9d12daf2c33f5959c8bf90aa513e4f65b561738661003029ec84830cd503a0c3" - HairpinMode: - description: | - Indicates if hairpin NAT should be enabled on the virtual interface. - type: "boolean" - example: false - LinkLocalIPv6Address: - description: IPv6 unicast address using the link-local prefix. - type: "string" - example: "fe80::42:acff:fe11:1" - LinkLocalIPv6PrefixLen: - description: Prefix length of the IPv6 unicast address. - type: "integer" - example: "64" - Ports: - $ref: "#/definitions/PortMap" - SandboxKey: - description: SandboxKey identifies the sandbox - type: "string" - example: "/var/run/docker/netns/8ab54b426c38" - - # TODO is SecondaryIPAddresses actually used? - SecondaryIPAddresses: - description: "" - type: "array" - items: - $ref: "#/definitions/Address" - x-nullable: true - - # TODO is SecondaryIPv6Addresses actually used? - SecondaryIPv6Addresses: - description: "" - type: "array" - items: - $ref: "#/definitions/Address" - x-nullable: true - - # TODO properties below are part of DefaultNetworkSettings, which is - # marked as deprecated since Docker 1.9 and to be removed in Docker v17.12 - EndpointID: - description: | - EndpointID uniquely represents a service endpoint in a Sandbox. - -


- - > **Deprecated**: This field is only propagated when attached to the - > default "bridge" network. Use the information from the "bridge" - > network inside the `Networks` map instead, which contains the same - > information. This field was deprecated in Docker 1.9 and is scheduled - > to be removed in Docker 17.12.0 - type: "string" - example: "b88f5b905aabf2893f3cbc4ee42d1ea7980bbc0a92e2c8922b1e1795298afb0b" - Gateway: - description: | - Gateway address for the default "bridge" network. - -


- - > **Deprecated**: This field is only propagated when attached to the - > default "bridge" network. Use the information from the "bridge" - > network inside the `Networks` map instead, which contains the same - > information. This field was deprecated in Docker 1.9 and is scheduled - > to be removed in Docker 17.12.0 - type: "string" - example: "172.17.0.1" - GlobalIPv6Address: - description: | - Global IPv6 address for the default "bridge" network. - -


- - > **Deprecated**: This field is only propagated when attached to the - > default "bridge" network. Use the information from the "bridge" - > network inside the `Networks` map instead, which contains the same - > information. This field was deprecated in Docker 1.9 and is scheduled - > to be removed in Docker 17.12.0 - type: "string" - example: "2001:db8::5689" - GlobalIPv6PrefixLen: - description: | - Mask length of the global IPv6 address. - -


- - > **Deprecated**: This field is only propagated when attached to the - > default "bridge" network. Use the information from the "bridge" - > network inside the `Networks` map instead, which contains the same - > information. This field was deprecated in Docker 1.9 and is scheduled - > to be removed in Docker 17.12.0 - type: "integer" - example: 64 - IPAddress: - description: | - IPv4 address for the default "bridge" network. - -


- - > **Deprecated**: This field is only propagated when attached to the - > default "bridge" network. Use the information from the "bridge" - > network inside the `Networks` map instead, which contains the same - > information. This field was deprecated in Docker 1.9 and is scheduled - > to be removed in Docker 17.12.0 - type: "string" - example: "172.17.0.4" - IPPrefixLen: - description: | - Mask length of the IPv4 address. - -


- - > **Deprecated**: This field is only propagated when attached to the - > default "bridge" network. Use the information from the "bridge" - > network inside the `Networks` map instead, which contains the same - > information. This field was deprecated in Docker 1.9 and is scheduled - > to be removed in Docker 17.12.0 - type: "integer" - example: 16 - IPv6Gateway: - description: | - IPv6 gateway address for this network. - -


- - > **Deprecated**: This field is only propagated when attached to the - > default "bridge" network. Use the information from the "bridge" - > network inside the `Networks` map instead, which contains the same - > information. This field was deprecated in Docker 1.9 and is scheduled - > to be removed in Docker 17.12.0 - type: "string" - example: "2001:db8:2::100" - MacAddress: - description: | - MAC address for the container on the default "bridge" network. - -


- - > **Deprecated**: This field is only propagated when attached to the - > default "bridge" network. Use the information from the "bridge" - > network inside the `Networks` map instead, which contains the same - > information. This field was deprecated in Docker 1.9 and is scheduled - > to be removed in Docker 17.12.0 - type: "string" - example: "02:42:ac:11:00:04" - Networks: - description: | - Information about all networks that the container is connected to. - type: "object" - additionalProperties: - $ref: "#/definitions/EndpointSettings" - - Address: - description: Address represents an IPv4 or IPv6 IP address. - type: "object" - properties: - Addr: - description: IP address. - type: "string" - PrefixLen: - description: Mask length of the IP address. - type: "integer" - - PortMap: - description: | - PortMap describes the mapping of container ports to host ports, using the - container's port-number and protocol as key in the format `/`, - for example, `80/udp`. - - If a container's port is mapped for multiple protocols, separate entries - are added to the mapping table. - type: "object" - additionalProperties: - type: "array" - x-nullable: true - items: - $ref: "#/definitions/PortBinding" - example: - "443/tcp": - - HostIp: "127.0.0.1" - HostPort: "4443" - "80/tcp": - - HostIp: "0.0.0.0" - HostPort: "80" - - HostIp: "0.0.0.0" - HostPort: "8080" - "80/udp": - - HostIp: "0.0.0.0" - HostPort: "80" - "53/udp": - - HostIp: "0.0.0.0" - HostPort: "53" - "2377/tcp": null - - PortBinding: - description: | - PortBinding represents a binding between a host IP address and a host - port. - type: "object" - properties: - HostIp: - description: "Host IP address that the container's port is mapped to." - type: "string" - example: "127.0.0.1" - HostPort: - description: "Host port number that the container's port is mapped to." - type: "string" - example: "4443" - - GraphDriverData: - description: "Information about a container's graph driver." - type: "object" - required: [Name, Data] - properties: - Name: - type: "string" - x-nullable: false - Data: - type: "object" - x-nullable: false - additionalProperties: - type: "string" - - Image: - type: "object" - required: - - Id - - Parent - - Comment - - Created - - Container - - DockerVersion - - Author - - Architecture - - Os - - Size - - VirtualSize - - GraphDriver - - RootFS - properties: - Id: - type: "string" - x-nullable: false - RepoTags: - type: "array" - items: - type: "string" - RepoDigests: - type: "array" - items: - type: "string" - Parent: - type: "string" - x-nullable: false - Comment: - type: "string" - x-nullable: false - Created: - type: "string" - x-nullable: false - Container: - type: "string" - x-nullable: false - ContainerConfig: - $ref: "#/definitions/ContainerConfig" - DockerVersion: - type: "string" - x-nullable: false - Author: - type: "string" - x-nullable: false - Config: - $ref: "#/definitions/ContainerConfig" - Architecture: - type: "string" - x-nullable: false - Os: - type: "string" - x-nullable: false - OsVersion: - type: "string" - Size: - type: "integer" - format: "int64" - x-nullable: false - VirtualSize: - type: "integer" - format: "int64" - x-nullable: false - GraphDriver: - $ref: "#/definitions/GraphDriverData" - RootFS: - type: "object" - required: [Type] - properties: - Type: - type: "string" - x-nullable: false - Layers: - type: "array" - items: - type: "string" - BaseLayer: - type: "string" - Metadata: - type: "object" - properties: - LastTagTime: - type: "string" - format: "dateTime" - - ImageSummary: - type: "object" - required: - - Id - - ParentId - - RepoTags - - RepoDigests - - Created - - Size - - SharedSize - - VirtualSize - - Labels - - Containers - properties: - Id: - type: "string" - x-nullable: false - ParentId: - type: "string" - x-nullable: false - RepoTags: - type: "array" - x-nullable: false - items: - type: "string" - RepoDigests: - type: "array" - x-nullable: false - items: - type: "string" - Created: - type: "integer" - x-nullable: false - Size: - type: "integer" - x-nullable: false - SharedSize: - type: "integer" - x-nullable: false - VirtualSize: - type: "integer" - x-nullable: false - Labels: - type: "object" - x-nullable: false - additionalProperties: - type: "string" - Containers: - x-nullable: false - type: "integer" - - AuthConfig: - type: "object" - properties: - username: - type: "string" - password: - type: "string" - email: - type: "string" - serveraddress: - type: "string" - example: - username: "hannibal" - password: "xxxx" - serveraddress: "https://index.docker.io/v1/" - - ProcessConfig: - type: "object" - properties: - privileged: - type: "boolean" - user: - type: "string" - tty: - type: "boolean" - entrypoint: - type: "string" - arguments: - type: "array" - items: - type: "string" - - Volume: - type: "object" - required: [Name, Driver, Mountpoint, Labels, Scope, Options] - properties: - Name: - type: "string" - description: "Name of the volume." - x-nullable: false - Driver: - type: "string" - description: "Name of the volume driver used by the volume." - x-nullable: false - Mountpoint: - type: "string" - description: "Mount path of the volume on the host." - x-nullable: false - CreatedAt: - type: "string" - format: "dateTime" - description: "Date/Time the volume was created." - Status: - type: "object" - description: | - Low-level details about the volume, provided by the volume driver. - Details are returned as a map with key/value pairs: - `{"key":"value","key2":"value2"}`. - - The `Status` field is optional, and is omitted if the volume driver - does not support this feature. - additionalProperties: - type: "object" - Labels: - type: "object" - description: "User-defined key/value metadata." - x-nullable: false - additionalProperties: - type: "string" - Scope: - type: "string" - description: | - The level at which the volume exists. Either `global` for cluster-wide, - or `local` for machine level. - default: "local" - x-nullable: false - enum: ["local", "global"] - Options: - type: "object" - description: | - The driver specific options used when creating the volume. - additionalProperties: - type: "string" - UsageData: - type: "object" - x-nullable: true - required: [Size, RefCount] - description: | - Usage details about the volume. This information is used by the - `GET /system/df` endpoint, and omitted in other endpoints. - properties: - Size: - type: "integer" - default: -1 - description: | - Amount of disk space used by the volume (in bytes). This information - is only available for volumes created with the `"local"` volume - driver. For volumes created with other volume drivers, this field - is set to `-1` ("not available") - x-nullable: false - RefCount: - type: "integer" - default: -1 - description: | - The number of containers referencing this volume. This field - is set to `-1` if the reference-count is not available. - x-nullable: false - - example: - Name: "tardis" - Driver: "custom" - Mountpoint: "/var/lib/docker/volumes/tardis" - Status: - hello: "world" - Labels: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" - Scope: "local" - CreatedAt: "2016-06-07T20:31:11.853781916Z" - - Network: - type: "object" - properties: - Name: - type: "string" - Id: - type: "string" - Created: - type: "string" - format: "dateTime" - Scope: - type: "string" - Driver: - type: "string" - EnableIPv6: - type: "boolean" - IPAM: - $ref: "#/definitions/IPAM" - Internal: - type: "boolean" - Attachable: - type: "boolean" - Ingress: - type: "boolean" - Containers: - type: "object" - additionalProperties: - $ref: "#/definitions/NetworkContainer" - Options: - type: "object" - additionalProperties: - type: "string" - Labels: - type: "object" - additionalProperties: - type: "string" - example: - Name: "net01" - Id: "7d86d31b1478e7cca9ebed7e73aa0fdeec46c5ca29497431d3007d2d9e15ed99" - Created: "2016-10-19T04:33:30.360899459Z" - Scope: "local" - Driver: "bridge" - EnableIPv6: false - IPAM: - Driver: "default" - Config: - - Subnet: "172.19.0.0/16" - Gateway: "172.19.0.1" - Options: - foo: "bar" - Internal: false - Attachable: false - Ingress: false - Containers: - 19a4d5d687db25203351ed79d478946f861258f018fe384f229f2efa4b23513c: - Name: "test" - EndpointID: "628cadb8bcb92de107b2a1e516cbffe463e321f548feb37697cce00ad694f21a" - MacAddress: "02:42:ac:13:00:02" - IPv4Address: "172.19.0.2/16" - IPv6Address: "" - Options: - com.docker.network.bridge.default_bridge: "true" - com.docker.network.bridge.enable_icc: "true" - com.docker.network.bridge.enable_ip_masquerade: "true" - com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" - com.docker.network.bridge.name: "docker0" - com.docker.network.driver.mtu: "1500" - Labels: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" - IPAM: - type: "object" - properties: - Driver: - description: "Name of the IPAM driver to use." - type: "string" - default: "default" - Config: - description: | - List of IPAM configuration options, specified as a map: - - ``` - {"Subnet": , "IPRange": , "Gateway": , "AuxAddress": } - ``` - type: "array" - items: - type: "object" - additionalProperties: - type: "string" - Options: - description: "Driver-specific options, specified as a map." - type: "object" - additionalProperties: - type: "string" - - NetworkContainer: - type: "object" - properties: - Name: - type: "string" - EndpointID: - type: "string" - MacAddress: - type: "string" - IPv4Address: - type: "string" - IPv6Address: - type: "string" - - BuildInfo: - type: "object" - properties: - id: - type: "string" - stream: - type: "string" - error: - type: "string" - errorDetail: - $ref: "#/definitions/ErrorDetail" - status: - type: "string" - progress: - type: "string" - progressDetail: - $ref: "#/definitions/ProgressDetail" - aux: - $ref: "#/definitions/ImageID" - - BuildCache: - type: "object" - properties: - ID: - type: "string" - Parent: - type: "string" - Type: - type: "string" - Description: - type: "string" - InUse: - type: "boolean" - Shared: - type: "boolean" - Size: - description: | - Amount of disk space used by the build cache (in bytes). - type: "integer" - CreatedAt: - description: | - Date and time at which the build cache was created in - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. - type: "string" - format: "dateTime" - example: "2016-08-18T10:44:24.496525531Z" - LastUsedAt: - description: | - Date and time at which the build cache was last used in - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. - type: "string" - format: "dateTime" - x-nullable: true - example: "2017-08-09T07:09:37.632105588Z" - UsageCount: - type: "integer" - - ImageID: - type: "object" - description: "Image ID or Digest" - properties: - ID: - type: "string" - example: - ID: "sha256:85f05633ddc1c50679be2b16a0479ab6f7637f8884e0cfe0f4d20e1ebb3d6e7c" - - CreateImageInfo: - type: "object" - properties: - id: - type: "string" - error: - type: "string" - status: - type: "string" - progress: - type: "string" - progressDetail: - $ref: "#/definitions/ProgressDetail" - - PushImageInfo: - type: "object" - properties: - error: - type: "string" - status: - type: "string" - progress: - type: "string" - progressDetail: - $ref: "#/definitions/ProgressDetail" - - ErrorDetail: - type: "object" - properties: - code: - type: "integer" - message: - type: "string" - - ProgressDetail: - type: "object" - properties: - current: - type: "integer" - total: - type: "integer" - - ErrorResponse: - description: "Represents an error." - type: "object" - required: ["message"] - properties: - message: - description: "The error message." - type: "string" - x-nullable: false - example: - message: "Something went wrong." - - IdResponse: - description: "Response to an API call that returns just an Id" - type: "object" - required: ["Id"] - properties: - Id: - description: "The id of the newly created object." - type: "string" - x-nullable: false - - EndpointSettings: - description: "Configuration for a network endpoint." - type: "object" - properties: - # Configurations - IPAMConfig: - $ref: "#/definitions/EndpointIPAMConfig" - Links: - type: "array" - items: - type: "string" - example: - - "container_1" - - "container_2" - Aliases: - type: "array" - items: - type: "string" - example: - - "server_x" - - "server_y" - - # Operational data - NetworkID: - description: | - Unique ID of the network. - type: "string" - example: "08754567f1f40222263eab4102e1c733ae697e8e354aa9cd6e18d7402835292a" - EndpointID: - description: | - Unique ID for the service endpoint in a Sandbox. - type: "string" - example: "b88f5b905aabf2893f3cbc4ee42d1ea7980bbc0a92e2c8922b1e1795298afb0b" - Gateway: - description: | - Gateway address for this network. - type: "string" - example: "172.17.0.1" - IPAddress: - description: | - IPv4 address. - type: "string" - example: "172.17.0.4" - IPPrefixLen: - description: | - Mask length of the IPv4 address. - type: "integer" - example: 16 - IPv6Gateway: - description: | - IPv6 gateway address. - type: "string" - example: "2001:db8:2::100" - GlobalIPv6Address: - description: | - Global IPv6 address. - type: "string" - example: "2001:db8::5689" - GlobalIPv6PrefixLen: - description: | - Mask length of the global IPv6 address. - type: "integer" - format: "int64" - example: 64 - MacAddress: - description: | - MAC address for the endpoint on this network. - type: "string" - example: "02:42:ac:11:00:04" - DriverOpts: - description: | - DriverOpts is a mapping of driver options and values. These options - are passed directly to the driver and are driver specific. - type: "object" - x-nullable: true - additionalProperties: - type: "string" - example: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" - - EndpointIPAMConfig: - description: | - EndpointIPAMConfig represents an endpoint's IPAM configuration. - type: "object" - x-nullable: true - properties: - IPv4Address: - type: "string" - example: "172.20.30.33" - IPv6Address: - type: "string" - example: "2001:db8:abcd::3033" - LinkLocalIPs: - type: "array" - items: - type: "string" - example: - - "169.254.34.68" - - "fe80::3468" - - PluginMount: - type: "object" - x-nullable: false - required: [Name, Description, Settable, Source, Destination, Type, Options] - properties: - Name: - type: "string" - x-nullable: false - example: "some-mount" - Description: - type: "string" - x-nullable: false - example: "This is a mount that's used by the plugin." - Settable: - type: "array" - items: - type: "string" - Source: - type: "string" - example: "/var/lib/docker/plugins/" - Destination: - type: "string" - x-nullable: false - example: "/mnt/state" - Type: - type: "string" - x-nullable: false - example: "bind" - Options: - type: "array" - items: - type: "string" - example: - - "rbind" - - "rw" - - PluginDevice: - type: "object" - required: [Name, Description, Settable, Path] - x-nullable: false - properties: - Name: - type: "string" - x-nullable: false - Description: - type: "string" - x-nullable: false - Settable: - type: "array" - items: - type: "string" - Path: - type: "string" - example: "/dev/fuse" - - PluginEnv: - type: "object" - x-nullable: false - required: [Name, Description, Settable, Value] - properties: - Name: - x-nullable: false - type: "string" - Description: - x-nullable: false - type: "string" - Settable: - type: "array" - items: - type: "string" - Value: - type: "string" - - PluginInterfaceType: - type: "object" - x-nullable: false - required: [Prefix, Capability, Version] - properties: - Prefix: - type: "string" - x-nullable: false - Capability: - type: "string" - x-nullable: false - Version: - type: "string" - x-nullable: false - - Plugin: - description: "A plugin for the Engine API" - type: "object" - required: [Settings, Enabled, Config, Name] - properties: - Id: - type: "string" - example: "5724e2c8652da337ab2eedd19fc6fc0ec908e4bd907c7421bf6a8dfc70c4c078" - Name: - type: "string" - x-nullable: false - example: "tiborvass/sample-volume-plugin" - Enabled: - description: - True if the plugin is running. False if the plugin is not running, - only installed. - type: "boolean" - x-nullable: false - example: true - Settings: - description: "Settings that can be modified by users." - type: "object" - x-nullable: false - required: [Args, Devices, Env, Mounts] - properties: - Mounts: - type: "array" - items: - $ref: "#/definitions/PluginMount" - Env: - type: "array" - items: - type: "string" - example: - - "DEBUG=0" - Args: - type: "array" - items: - type: "string" - Devices: - type: "array" - items: - $ref: "#/definitions/PluginDevice" - PluginReference: - description: "plugin remote reference used to push/pull the plugin" - type: "string" - x-nullable: false - example: "localhost:5000/tiborvass/sample-volume-plugin:latest" - Config: - description: "The config of a plugin." - type: "object" - x-nullable: false - required: - - Description - - Documentation - - Interface - - Entrypoint - - WorkDir - - Network - - Linux - - PidHost - - PropagatedMount - - IpcHost - - Mounts - - Env - - Args - properties: - DockerVersion: - description: "Docker Version used to create the plugin" - type: "string" - x-nullable: false - example: "17.06.0-ce" - Description: - type: "string" - x-nullable: false - example: "A sample volume plugin for Docker" - Documentation: - type: "string" - x-nullable: false - example: "https://docs.docker.com/engine/extend/plugins/" - Interface: - description: "The interface between Docker and the plugin" - x-nullable: false - type: "object" - required: [Types, Socket] - properties: - Types: - type: "array" - items: - $ref: "#/definitions/PluginInterfaceType" - example: - - "docker.volumedriver/1.0" - Socket: - type: "string" - x-nullable: false - example: "plugins.sock" - ProtocolScheme: - type: "string" - example: "some.protocol/v1.0" - description: "Protocol to use for clients connecting to the plugin." - enum: - - "" - - "moby.plugins.http/v1" - Entrypoint: - type: "array" - items: - type: "string" - example: - - "/usr/bin/sample-volume-plugin" - - "/data" - WorkDir: - type: "string" - x-nullable: false - example: "/bin/" - User: - type: "object" - x-nullable: false - properties: - UID: - type: "integer" - format: "uint32" - example: 1000 - GID: - type: "integer" - format: "uint32" - example: 1000 - Network: - type: "object" - x-nullable: false - required: [Type] - properties: - Type: - x-nullable: false - type: "string" - example: "host" - Linux: - type: "object" - x-nullable: false - required: [Capabilities, AllowAllDevices, Devices] - properties: - Capabilities: - type: "array" - items: - type: "string" - example: - - "CAP_SYS_ADMIN" - - "CAP_SYSLOG" - AllowAllDevices: - type: "boolean" - x-nullable: false - example: false - Devices: - type: "array" - items: - $ref: "#/definitions/PluginDevice" - PropagatedMount: - type: "string" - x-nullable: false - example: "/mnt/volumes" - IpcHost: - type: "boolean" - x-nullable: false - example: false - PidHost: - type: "boolean" - x-nullable: false - example: false - Mounts: - type: "array" - items: - $ref: "#/definitions/PluginMount" - Env: - type: "array" - items: - $ref: "#/definitions/PluginEnv" - example: - - Name: "DEBUG" - Description: "If set, prints debug messages" - Settable: null - Value: "0" - Args: - type: "object" - x-nullable: false - required: [Name, Description, Settable, Value] - properties: - Name: - x-nullable: false - type: "string" - example: "args" - Description: - x-nullable: false - type: "string" - example: "command line arguments" - Settable: - type: "array" - items: - type: "string" - Value: - type: "array" - items: - type: "string" - rootfs: - type: "object" - properties: - type: - type: "string" - example: "layers" - diff_ids: - type: "array" - items: - type: "string" - example: - - "sha256:675532206fbf3030b8458f88d6e26d4eb1577688a25efec97154c94e8b6b4887" - - "sha256:e216a057b1cb1efc11f8a268f37ef62083e70b1b38323ba252e25ac88904a7e8" - - ObjectVersion: - description: | - The version number of the object such as node, service, etc. This is needed - to avoid conflicting writes. The client must send the version number along - with the modified specification when updating these objects. - - This approach ensures safe concurrency and determinism in that the change - on the object may not be applied if the version number has changed from the - last read. In other words, if two update requests specify the same base - version, only one of the requests can succeed. As a result, two separate - update requests that happen at the same time will not unintentionally - overwrite each other. - type: "object" - properties: - Index: - type: "integer" - format: "uint64" - example: 373531 - - NodeSpec: - type: "object" - properties: - Name: - description: "Name for the node." - type: "string" - example: "my-node" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - Role: - description: "Role of the node." - type: "string" - enum: - - "worker" - - "manager" - example: "manager" - Availability: - description: "Availability of the node." - type: "string" - enum: - - "active" - - "pause" - - "drain" - example: "active" - example: - Availability: "active" - Name: "node-name" - Role: "manager" - Labels: - foo: "bar" - - Node: - type: "object" - properties: - ID: - type: "string" - example: "24ifsmvkjbyhk" - Version: - $ref: "#/definitions/ObjectVersion" - CreatedAt: - description: | - Date and time at which the node was added to the swarm in - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. - type: "string" - format: "dateTime" - example: "2016-08-18T10:44:24.496525531Z" - UpdatedAt: - description: | - Date and time at which the node was last updated in - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. - type: "string" - format: "dateTime" - example: "2017-08-09T07:09:37.632105588Z" - Spec: - $ref: "#/definitions/NodeSpec" - Description: - $ref: "#/definitions/NodeDescription" - Status: - $ref: "#/definitions/NodeStatus" - ManagerStatus: - $ref: "#/definitions/ManagerStatus" - - NodeDescription: - description: | - NodeDescription encapsulates the properties of the Node as reported by the - agent. - type: "object" - properties: - Hostname: - type: "string" - example: "bf3067039e47" - Platform: - $ref: "#/definitions/Platform" - Resources: - $ref: "#/definitions/ResourceObject" - Engine: - $ref: "#/definitions/EngineDescription" - TLSInfo: - $ref: "#/definitions/TLSInfo" - - Platform: - description: | - Platform represents the platform (Arch/OS). - type: "object" - properties: - Architecture: - description: | - Architecture represents the hardware architecture (for example, - `x86_64`). - type: "string" - example: "x86_64" - OS: - description: | - OS represents the Operating System (for example, `linux` or `windows`). - type: "string" - example: "linux" - - EngineDescription: - description: "EngineDescription provides information about an engine." - type: "object" - properties: - EngineVersion: - type: "string" - example: "17.06.0" - Labels: - type: "object" - additionalProperties: - type: "string" - example: - foo: "bar" - Plugins: - type: "array" - items: - type: "object" - properties: - Type: - type: "string" - Name: - type: "string" - example: - - Type: "Log" - Name: "awslogs" - - Type: "Log" - Name: "fluentd" - - Type: "Log" - Name: "gcplogs" - - Type: "Log" - Name: "gelf" - - Type: "Log" - Name: "journald" - - Type: "Log" - Name: "json-file" - - Type: "Log" - Name: "logentries" - - Type: "Log" - Name: "splunk" - - Type: "Log" - Name: "syslog" - - Type: "Network" - Name: "bridge" - - Type: "Network" - Name: "host" - - Type: "Network" - Name: "ipvlan" - - Type: "Network" - Name: "macvlan" - - Type: "Network" - Name: "null" - - Type: "Network" - Name: "overlay" - - Type: "Volume" - Name: "local" - - Type: "Volume" - Name: "localhost:5000/vieux/sshfs:latest" - - Type: "Volume" - Name: "vieux/sshfs:latest" - - TLSInfo: - description: | - Information about the issuer of leaf TLS certificates and the trusted root - CA certificate. - type: "object" - properties: - TrustRoot: - description: | - The root CA certificate(s) that are used to validate leaf TLS - certificates. - type: "string" - CertIssuerSubject: - description: - The base64-url-safe-encoded raw subject bytes of the issuer. - type: "string" - CertIssuerPublicKey: - description: | - The base64-url-safe-encoded raw public key bytes of the issuer. - type: "string" - example: - TrustRoot: | - -----BEGIN CERTIFICATE----- - MIIBajCCARCgAwIBAgIUbYqrLSOSQHoxD8CwG6Bi2PJi9c8wCgYIKoZIzj0EAwIw - EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTcwNDI0MjE0MzAwWhcNMzcwNDE5MjE0 - MzAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH - A0IABJk/VyMPYdaqDXJb/VXh5n/1Yuv7iNrxV3Qb3l06XD46seovcDWs3IZNV1lf - 3Skyr0ofcchipoiHkXBODojJydSjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB - Af8EBTADAQH/MB0GA1UdDgQWBBRUXxuRcnFjDfR/RIAUQab8ZV/n4jAKBggqhkjO - PQQDAgNIADBFAiAy+JTe6Uc3KyLCMiqGl2GyWGQqQDEcO3/YG36x7om65AIhAJvz - pxv6zFeVEkAEEkqIYi0omA9+CjanB/6Bz4n1uw8H - -----END CERTIFICATE----- - CertIssuerSubject: "MBMxETAPBgNVBAMTCHN3YXJtLWNh" - CertIssuerPublicKey: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmT9XIw9h1qoNclv9VeHmf/Vi6/uI2vFXdBveXTpcPjqx6i9wNazchk1XWV/dKTKvSh9xyGKmiIeRcE4OiMnJ1A==" - - NodeStatus: - description: | - NodeStatus represents the status of a node. - - It provides the current status of the node, as seen by the manager. - type: "object" - properties: - State: - $ref: "#/definitions/NodeState" - Message: - type: "string" - example: "" - Addr: - description: "IP address of the node." - type: "string" - example: "172.17.0.2" - - NodeState: - description: "NodeState represents the state of a node." - type: "string" - enum: - - "unknown" - - "down" - - "ready" - - "disconnected" - example: "ready" - - ManagerStatus: - description: | - ManagerStatus represents the status of a manager. - - It provides the current status of a node's manager component, if the node - is a manager. - x-nullable: true - type: "object" - properties: - Leader: - type: "boolean" - default: false - example: true - Reachability: - $ref: "#/definitions/Reachability" - Addr: - description: | - The IP address and port at which the manager is reachable. - type: "string" - example: "10.0.0.46:2377" - - Reachability: - description: "Reachability represents the reachability of a node." - type: "string" - enum: - - "unknown" - - "unreachable" - - "reachable" - example: "reachable" - - SwarmSpec: - description: "User modifiable swarm configuration." - type: "object" - properties: - Name: - description: "Name of the swarm." - type: "string" - example: "default" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - example: - com.example.corp.type: "production" - com.example.corp.department: "engineering" - Orchestration: - description: "Orchestration configuration." - type: "object" - x-nullable: true - properties: - TaskHistoryRetentionLimit: - description: | - The number of historic tasks to keep per instance or node. If - negative, never remove completed or failed tasks. - type: "integer" - format: "int64" - example: 10 - Raft: - description: "Raft configuration." - type: "object" - properties: - SnapshotInterval: - description: "The number of log entries between snapshots." - type: "integer" - format: "uint64" - example: 10000 - KeepOldSnapshots: - description: | - The number of snapshots to keep beyond the current snapshot. - type: "integer" - format: "uint64" - LogEntriesForSlowFollowers: - description: | - The number of log entries to keep around to sync up slow followers - after a snapshot is created. - type: "integer" - format: "uint64" - example: 500 - ElectionTick: - description: | - The number of ticks that a follower will wait for a message from - the leader before becoming a candidate and starting an election. - `ElectionTick` must be greater than `HeartbeatTick`. - - A tick currently defaults to one second, so these translate - directly to seconds currently, but this is NOT guaranteed. - type: "integer" - example: 3 - HeartbeatTick: - description: | - The number of ticks between heartbeats. Every HeartbeatTick ticks, - the leader will send a heartbeat to the followers. - - A tick currently defaults to one second, so these translate - directly to seconds currently, but this is NOT guaranteed. - type: "integer" - example: 1 - Dispatcher: - description: "Dispatcher configuration." - type: "object" - x-nullable: true - properties: - HeartbeatPeriod: - description: | - The delay for an agent to send a heartbeat to the dispatcher. - type: "integer" - format: "int64" - example: 5000000000 - CAConfig: - description: "CA configuration." - type: "object" - x-nullable: true - properties: - NodeCertExpiry: - description: "The duration node certificates are issued for." - type: "integer" - format: "int64" - example: 7776000000000000 - ExternalCAs: - description: | - Configuration for forwarding signing requests to an external - certificate authority. - type: "array" - items: - type: "object" - properties: - Protocol: - description: | - Protocol for communication with the external CA (currently - only `cfssl` is supported). - type: "string" - enum: - - "cfssl" - default: "cfssl" - URL: - description: | - URL where certificate signing requests should be sent. - type: "string" - Options: - description: | - An object with key/value pairs that are interpreted as - protocol-specific options for the external CA driver. - type: "object" - additionalProperties: - type: "string" - CACert: - description: | - The root CA certificate (in PEM format) this external CA uses - to issue TLS certificates (assumed to be to the current swarm - root CA certificate if not provided). - type: "string" - SigningCACert: - description: | - The desired signing CA certificate for all swarm node TLS leaf - certificates, in PEM format. - type: "string" - SigningCAKey: - description: | - The desired signing CA key for all swarm node TLS leaf certificates, - in PEM format. - type: "string" - ForceRotate: - description: | - An integer whose purpose is to force swarm to generate a new - signing CA certificate and key, if none have been specified in - `SigningCACert` and `SigningCAKey` - format: "uint64" - type: "integer" - EncryptionConfig: - description: "Parameters related to encryption-at-rest." - type: "object" - properties: - AutoLockManagers: - description: | - If set, generate a key and use it to lock data stored on the - managers. - type: "boolean" - example: false - TaskDefaults: - description: "Defaults for creating tasks in this cluster." - type: "object" - properties: - LogDriver: - description: | - The log driver to use for tasks created in the orchestrator if - unspecified by a service. - - Updating this value only affects new tasks. Existing tasks continue - to use their previously configured log driver until recreated. - type: "object" - properties: - Name: - description: | - The log driver to use as a default for new tasks. - type: "string" - example: "json-file" - Options: - description: | - Driver-specific options for the selectd log driver, specified - as key/value pairs. - type: "object" - additionalProperties: - type: "string" - example: - "max-file": "10" - "max-size": "100m" - - # The Swarm information for `GET /info`. It is the same as `GET /swarm`, but - # without `JoinTokens`. - ClusterInfo: - description: | - ClusterInfo represents information about the swarm as is returned by the - "/info" endpoint. Join-tokens are not included. - x-nullable: true - type: "object" - properties: - ID: - description: "The ID of the swarm." - type: "string" - example: "abajmipo7b4xz5ip2nrla6b11" - Version: - $ref: "#/definitions/ObjectVersion" - CreatedAt: - description: | - Date and time at which the swarm was initialised in - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. - type: "string" - format: "dateTime" - example: "2016-08-18T10:44:24.496525531Z" - UpdatedAt: - description: | - Date and time at which the swarm was last updated in - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. - type: "string" - format: "dateTime" - example: "2017-08-09T07:09:37.632105588Z" - Spec: - $ref: "#/definitions/SwarmSpec" - TLSInfo: - $ref: "#/definitions/TLSInfo" - RootRotationInProgress: - description: | - Whether there is currently a root CA rotation in progress for the swarm - type: "boolean" - example: false - DataPathPort: - description: | - DataPathPort specifies the data path port number for data traffic. - Acceptable port range is 1024 to 49151. - If no port is set or is set to 0, the default port (4789) is used. - type: "integer" - format: "uint32" - default: 4789 - example: 4789 - DefaultAddrPool: - description: | - Default Address Pool specifies default subnet pools for global scope - networks. - type: "array" - items: - type: "string" - format: "CIDR" - example: ["10.10.0.0/16", "20.20.0.0/16"] - SubnetSize: - description: | - SubnetSize specifies the subnet size of the networks created from the - default subnet pool. - type: "integer" - format: "uint32" - maximum: 29 - default: 24 - example: 24 - - JoinTokens: - description: | - JoinTokens contains the tokens workers and managers need to join the swarm. - type: "object" - properties: - Worker: - description: | - The token workers can use to join the swarm. - type: "string" - example: "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx" - Manager: - description: | - The token managers can use to join the swarm. - type: "string" - example: "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2" - - Swarm: - type: "object" - allOf: - - $ref: "#/definitions/ClusterInfo" - - type: "object" - properties: - JoinTokens: - $ref: "#/definitions/JoinTokens" - - TaskSpec: - description: "User modifiable task configuration." - type: "object" - properties: - PluginSpec: - type: "object" - description: | - Plugin spec for the service. *(Experimental release only.)* - -


- - > **Note**: ContainerSpec, NetworkAttachmentSpec, and PluginSpec are - > mutually exclusive. PluginSpec is only used when the Runtime field - > is set to `plugin`. NetworkAttachmentSpec is used when the Runtime - > field is set to `attachment`. - properties: - Name: - description: "The name or 'alias' to use for the plugin." - type: "string" - Remote: - description: "The plugin image reference to use." - type: "string" - Disabled: - description: "Disable the plugin once scheduled." - type: "boolean" - PluginPrivilege: - type: "array" - items: - description: | - Describes a permission accepted by the user upon installing the - plugin. - type: "object" - properties: - Name: - type: "string" - Description: - type: "string" - Value: - type: "array" - items: - type: "string" - ContainerSpec: - type: "object" - description: | - Container spec for the service. - -


- - > **Note**: ContainerSpec, NetworkAttachmentSpec, and PluginSpec are - > mutually exclusive. PluginSpec is only used when the Runtime field - > is set to `plugin`. NetworkAttachmentSpec is used when the Runtime - > field is set to `attachment`. - properties: - Image: - description: "The image name to use for the container" - type: "string" - Labels: - description: "User-defined key/value data." - type: "object" - additionalProperties: - type: "string" - Command: - description: "The command to be run in the image." - type: "array" - items: - type: "string" - Args: - description: "Arguments to the command." - type: "array" - items: - type: "string" - Hostname: - description: | - The hostname to use for the container, as a valid - [RFC 1123](https://tools.ietf.org/html/rfc1123) hostname. - type: "string" - Env: - description: | - A list of environment variables in the form `VAR=value`. - type: "array" - items: - type: "string" - Dir: - description: "The working directory for commands to run in." - type: "string" - User: - description: "The user inside the container." - type: "string" - Groups: - type: "array" - description: | - A list of additional groups that the container process will run as. - items: - type: "string" - Privileges: - type: "object" - description: "Security options for the container" - properties: - CredentialSpec: - type: "object" - description: "CredentialSpec for managed service account (Windows only)" - properties: - Config: - type: "string" - example: "0bt9dmxjvjiqermk6xrop3ekq" - description: | - Load credential spec from a Swarm Config with the given ID. - The specified config must also be present in the Configs - field with the Runtime property set. - -


- - - > **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, - > and `CredentialSpec.Config` are mutually exclusive. - File: - type: "string" - example: "spec.json" - description: | - Load credential spec from this file. The file is read by - the daemon, and must be present in the `CredentialSpecs` - subdirectory in the docker data directory, which defaults - to `C:\ProgramData\Docker\` on Windows. - - For example, specifying `spec.json` loads - `C:\ProgramData\Docker\CredentialSpecs\spec.json`. - -


- - > **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, - > and `CredentialSpec.Config` are mutually exclusive. - Registry: - type: "string" - description: | - Load credential spec from this value in the Windows - registry. The specified registry value must be located in: - - `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs` - -


- - - > **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, - > and `CredentialSpec.Config` are mutually exclusive. - SELinuxContext: - type: "object" - description: "SELinux labels of the container" - properties: - Disable: - type: "boolean" - description: "Disable SELinux" - User: - type: "string" - description: "SELinux user label" - Role: - type: "string" - description: "SELinux role label" - Type: - type: "string" - description: "SELinux type label" - Level: - type: "string" - description: "SELinux level label" - TTY: - description: "Whether a pseudo-TTY should be allocated." - type: "boolean" - OpenStdin: - description: "Open `stdin`" - type: "boolean" - ReadOnly: - description: "Mount the container's root filesystem as read only." - type: "boolean" - Mounts: - description: | - Specification for mounts to be added to containers created as part - of the service. - type: "array" - items: - $ref: "#/definitions/Mount" - StopSignal: - description: "Signal to stop the container." - type: "string" - StopGracePeriod: - description: | - Amount of time to wait for the container to terminate before - forcefully killing it. - type: "integer" - format: "int64" - HealthCheck: - $ref: "#/definitions/HealthConfig" - Hosts: - type: "array" - description: | - A list of hostname/IP mappings to add to the container's `hosts` - file. The format of extra hosts is specified in the - [hosts(5)](http://man7.org/linux/man-pages/man5/hosts.5.html) - man page: - - IP_address canonical_hostname [aliases...] - items: - type: "string" - DNSConfig: - description: | - Specification for DNS related configurations in resolver configuration - file (`resolv.conf`). - type: "object" - properties: - Nameservers: - description: "The IP addresses of the name servers." - type: "array" - items: - type: "string" - Search: - description: "A search list for host-name lookup." - type: "array" - items: - type: "string" - Options: - description: | - A list of internal resolver variables to be modified (e.g., - `debug`, `ndots:3`, etc.). - type: "array" - items: - type: "string" - Secrets: - description: | - Secrets contains references to zero or more secrets that will be - exposed to the service. - type: "array" - items: - type: "object" - properties: - File: - description: | - File represents a specific target that is backed by a file. - type: "object" - properties: - Name: - description: | - Name represents the final filename in the filesystem. - type: "string" - UID: - description: "UID represents the file UID." - type: "string" - GID: - description: "GID represents the file GID." - type: "string" - Mode: - description: "Mode represents the FileMode of the file." - type: "integer" - format: "uint32" - SecretID: - description: | - SecretID represents the ID of the specific secret that we're - referencing. - type: "string" - SecretName: - description: | - SecretName is the name of the secret that this references, - but this is just provided for lookup/display purposes. The - secret in the reference will be identified by its ID. - type: "string" - Configs: - description: | - Configs contains references to zero or more configs that will be - exposed to the service. - type: "array" - items: - type: "object" - properties: - File: - description: | - File represents a specific target that is backed by a file. - -


- - > **Note**: `Configs.File` and `Configs.Runtime` are mutually exclusive - type: "object" - properties: - Name: - description: | - Name represents the final filename in the filesystem. - type: "string" - UID: - description: "UID represents the file UID." - type: "string" - GID: - description: "GID represents the file GID." - type: "string" - Mode: - description: "Mode represents the FileMode of the file." - type: "integer" - format: "uint32" - Runtime: - description: | - Runtime represents a target that is not mounted into the - container but is used by the task - -


- - > **Note**: `Configs.File` and `Configs.Runtime` are mutually - > exclusive - type: "object" - ConfigID: - description: | - ConfigID represents the ID of the specific config that we're - referencing. - type: "string" - ConfigName: - description: | - ConfigName is the name of the config that this references, - but this is just provided for lookup/display purposes. The - config in the reference will be identified by its ID. - type: "string" - Isolation: - type: "string" - description: | - Isolation technology of the containers running the service. - (Windows only) - enum: - - "default" - - "process" - - "hyperv" - Init: - description: | - Run an init inside the container that forwards signals and reaps - processes. This field is omitted if empty, and the default (as - configured on the daemon) is used. - type: "boolean" - x-nullable: true - Sysctls: - description: | - Set kernel namedspaced parameters (sysctls) in the container. - The Sysctls option on services accepts the same sysctls as the - are supported on containers. Note that while the same sysctls are - supported, no guarantees or checks are made about their - suitability for a clustered environment, and it's up to the user - to determine whether a given sysctl will work properly in a - Service. - type: "object" - additionalProperties: - type: "string" - # This option is not used by Windows containers - CapabilityAdd: - type: "array" - description: | - A list of kernel capabilities to add to the default set - for the container. - items: - type: "string" - example: - - "CAP_NET_RAW" - - "CAP_SYS_ADMIN" - - "CAP_SYS_CHROOT" - - "CAP_SYSLOG" - CapabilityDrop: - type: "array" - description: | - A list of kernel capabilities to drop from the default set - for the container. - items: - type: "string" - example: - - "CAP_NET_RAW" - Ulimits: - description: | - A list of resource limits to set in the container. For example: `{"Name": "nofile", "Soft": 1024, "Hard": 2048}`" - type: "array" - items: - type: "object" - properties: - Name: - description: "Name of ulimit" - type: "string" - Soft: - description: "Soft limit" - type: "integer" - Hard: - description: "Hard limit" - type: "integer" - NetworkAttachmentSpec: - description: | - Read-only spec type for non-swarm containers attached to swarm overlay - networks. - -


- - > **Note**: ContainerSpec, NetworkAttachmentSpec, and PluginSpec are - > mutually exclusive. PluginSpec is only used when the Runtime field - > is set to `plugin`. NetworkAttachmentSpec is used when the Runtime - > field is set to `attachment`. - type: "object" - properties: - ContainerID: - description: "ID of the container represented by this task" - type: "string" - Resources: - description: | - Resource requirements which apply to each individual container created - as part of the service. - type: "object" - properties: - Limits: - description: "Define resources limits." - $ref: "#/definitions/Limit" - Reservation: - description: "Define resources reservation." - $ref: "#/definitions/ResourceObject" - RestartPolicy: - description: | - Specification for the restart policy which applies to containers - created as part of this service. - type: "object" - properties: - Condition: - description: "Condition for restart." - type: "string" - enum: - - "none" - - "on-failure" - - "any" - Delay: - description: "Delay between restart attempts." - type: "integer" - format: "int64" - MaxAttempts: - description: | - Maximum attempts to restart a given container before giving up - (default value is 0, which is ignored). - type: "integer" - format: "int64" - default: 0 - Window: - description: | - Windows is the time window used to evaluate the restart policy - (default value is 0, which is unbounded). - type: "integer" - format: "int64" - default: 0 - Placement: - type: "object" - properties: - Constraints: - description: | - An array of constraint expressions to limit the set of nodes where - a task can be scheduled. Constraint expressions can either use a - _match_ (`==`) or _exclude_ (`!=`) rule. Multiple constraints find - nodes that satisfy every expression (AND match). Constraints can - match node or Docker Engine labels as follows: - - node attribute | matches | example - ---------------------|--------------------------------|----------------------------------------------- - `node.id` | Node ID | `node.id==2ivku8v2gvtg4` - `node.hostname` | Node hostname | `node.hostname!=node-2` - `node.role` | Node role (`manager`/`worker`) | `node.role==manager` - `node.platform.os` | Node operating system | `node.platform.os==windows` - `node.platform.arch` | Node architecture | `node.platform.arch==x86_64` - `node.labels` | User-defined node labels | `node.labels.security==high` - `engine.labels` | Docker Engine's labels | `engine.labels.operatingsystem==ubuntu-14.04` - - `engine.labels` apply to Docker Engine labels like operating system, - drivers, etc. Swarm administrators add `node.labels` for operational - purposes by using the [`node update endpoint`](#operation/NodeUpdate). - - type: "array" - items: - type: "string" - example: - - "node.hostname!=node3.corp.example.com" - - "node.role!=manager" - - "node.labels.type==production" - - "node.platform.os==linux" - - "node.platform.arch==x86_64" - Preferences: - description: | - Preferences provide a way to make the scheduler aware of factors - such as topology. They are provided in order from highest to - lowest precedence. - type: "array" - items: - type: "object" - properties: - Spread: - type: "object" - properties: - SpreadDescriptor: - description: | - label descriptor, such as `engine.labels.az`. - type: "string" - example: - - Spread: - SpreadDescriptor: "node.labels.datacenter" - - Spread: - SpreadDescriptor: "node.labels.rack" - MaxReplicas: - description: | - Maximum number of replicas for per node (default value is 0, which - is unlimited) - type: "integer" - format: "int64" - default: 0 - Platforms: - description: | - Platforms stores all the platforms that the service's image can - run on. This field is used in the platform filter for scheduling. - If empty, then the platform filter is off, meaning there are no - scheduling restrictions. - type: "array" - items: - $ref: "#/definitions/Platform" - ForceUpdate: - description: | - A counter that triggers an update even if no relevant parameters have - been changed. - type: "integer" - Runtime: - description: | - Runtime is the type of runtime specified for the task executor. - type: "string" - Networks: - description: "Specifies which networks the service should attach to." - type: "array" - items: - $ref: "#/definitions/NetworkAttachmentConfig" - LogDriver: - description: | - Specifies the log driver to use for tasks created from this spec. If - not present, the default one for the swarm will be used, finally - falling back to the engine default if not specified. - type: "object" - properties: - Name: - type: "string" - Options: - type: "object" - additionalProperties: - type: "string" - - TaskState: - type: "string" - enum: - - "new" - - "allocated" - - "pending" - - "assigned" - - "accepted" - - "preparing" - - "ready" - - "starting" - - "running" - - "complete" - - "shutdown" - - "failed" - - "rejected" - - "remove" - - "orphaned" - - Task: - type: "object" - properties: - ID: - description: "The ID of the task." - type: "string" - Version: - $ref: "#/definitions/ObjectVersion" - CreatedAt: - type: "string" - format: "dateTime" - UpdatedAt: - type: "string" - format: "dateTime" - Name: - description: "Name of the task." - type: "string" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - Spec: - $ref: "#/definitions/TaskSpec" - ServiceID: - description: "The ID of the service this task is part of." - type: "string" - Slot: - type: "integer" - NodeID: - description: "The ID of the node that this task is on." - type: "string" - AssignedGenericResources: - $ref: "#/definitions/GenericResources" - Status: - type: "object" - properties: - Timestamp: - type: "string" - format: "dateTime" - State: - $ref: "#/definitions/TaskState" - Message: - type: "string" - Err: - type: "string" - ContainerStatus: - type: "object" - properties: - ContainerID: - type: "string" - PID: - type: "integer" - ExitCode: - type: "integer" - DesiredState: - $ref: "#/definitions/TaskState" - JobIteration: - description: | - If the Service this Task belongs to is a job-mode service, contains - the JobIteration of the Service this Task was created for. Absent if - the Task was created for a Replicated or Global Service. - $ref: "#/definitions/ObjectVersion" - example: - ID: "0kzzo1i0y4jz6027t0k7aezc7" - Version: - Index: 71 - CreatedAt: "2016-06-07T21:07:31.171892745Z" - UpdatedAt: "2016-06-07T21:07:31.376370513Z" - Spec: - ContainerSpec: - Image: "redis" - Resources: - Limits: {} - Reservations: {} - RestartPolicy: - Condition: "any" - MaxAttempts: 0 - Placement: {} - ServiceID: "9mnpnzenvg8p8tdbtq4wvbkcz" - Slot: 1 - NodeID: "60gvrl6tm78dmak4yl7srz94v" - Status: - Timestamp: "2016-06-07T21:07:31.290032978Z" - State: "running" - Message: "started" - ContainerStatus: - ContainerID: "e5d62702a1b48d01c3e02ca1e0212a250801fa8d67caca0b6f35919ebc12f035" - PID: 677 - DesiredState: "running" - NetworksAttachments: - - Network: - ID: "4qvuz4ko70xaltuqbt8956gd1" - Version: - Index: 18 - CreatedAt: "2016-06-07T20:31:11.912919752Z" - UpdatedAt: "2016-06-07T21:07:29.955277358Z" - Spec: - Name: "ingress" - Labels: - com.docker.swarm.internal: "true" - DriverConfiguration: {} - IPAMOptions: - Driver: {} - Configs: - - Subnet: "10.255.0.0/16" - Gateway: "10.255.0.1" - DriverState: - Name: "overlay" - Options: - com.docker.network.driver.overlay.vxlanid_list: "256" - IPAMOptions: - Driver: - Name: "default" - Configs: - - Subnet: "10.255.0.0/16" - Gateway: "10.255.0.1" - Addresses: - - "10.255.0.10/16" - AssignedGenericResources: - - DiscreteResourceSpec: - Kind: "SSD" - Value: 3 - - NamedResourceSpec: - Kind: "GPU" - Value: "UUID1" - - NamedResourceSpec: - Kind: "GPU" - Value: "UUID2" - - ServiceSpec: - description: "User modifiable configuration for a service." - properties: - Name: - description: "Name of the service." - type: "string" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - TaskTemplate: - $ref: "#/definitions/TaskSpec" - Mode: - description: "Scheduling mode for the service." - type: "object" - properties: - Replicated: - type: "object" - properties: - Replicas: - type: "integer" - format: "int64" - Global: - type: "object" - ReplicatedJob: - description: | - The mode used for services with a finite number of tasks that run - to a completed state. - type: "object" - properties: - MaxConcurrent: - description: | - The maximum number of replicas to run simultaneously. - type: "integer" - format: "int64" - default: 1 - TotalCompletions: - description: | - The total number of replicas desired to reach the Completed - state. If unset, will default to the value of `MaxConcurrent` - type: "integer" - format: "int64" - GlobalJob: - description: | - The mode used for services which run a task to the completed state - on each valid node. - type: "object" - UpdateConfig: - description: "Specification for the update strategy of the service." - type: "object" - properties: - Parallelism: - description: | - Maximum number of tasks to be updated in one iteration (0 means - unlimited parallelism). - type: "integer" - format: "int64" - Delay: - description: "Amount of time between updates, in nanoseconds." - type: "integer" - format: "int64" - FailureAction: - description: | - Action to take if an updated task fails to run, or stops running - during the update. - type: "string" - enum: - - "continue" - - "pause" - - "rollback" - Monitor: - description: | - Amount of time to monitor each updated task for failures, in - nanoseconds. - type: "integer" - format: "int64" - MaxFailureRatio: - description: | - The fraction of tasks that may fail during an update before the - failure action is invoked, specified as a floating point number - between 0 and 1. - type: "number" - default: 0 - Order: - description: | - The order of operations when rolling out an updated task. Either - the old task is shut down before the new task is started, or the - new task is started before the old task is shut down. - type: "string" - enum: - - "stop-first" - - "start-first" - RollbackConfig: - description: "Specification for the rollback strategy of the service." - type: "object" - properties: - Parallelism: - description: | - Maximum number of tasks to be rolled back in one iteration (0 means - unlimited parallelism). - type: "integer" - format: "int64" - Delay: - description: | - Amount of time between rollback iterations, in nanoseconds. - type: "integer" - format: "int64" - FailureAction: - description: | - Action to take if an rolled back task fails to run, or stops - running during the rollback. - type: "string" - enum: - - "continue" - - "pause" - Monitor: - description: | - Amount of time to monitor each rolled back task for failures, in - nanoseconds. - type: "integer" - format: "int64" - MaxFailureRatio: - description: | - The fraction of tasks that may fail during a rollback before the - failure action is invoked, specified as a floating point number - between 0 and 1. - type: "number" - default: 0 - Order: - description: | - The order of operations when rolling back a task. Either the old - task is shut down before the new task is started, or the new task - is started before the old task is shut down. - type: "string" - enum: - - "stop-first" - - "start-first" - Networks: - description: "Specifies which networks the service should attach to." - type: "array" - items: - $ref: "#/definitions/NetworkAttachmentConfig" - - EndpointSpec: - $ref: "#/definitions/EndpointSpec" - - EndpointPortConfig: - type: "object" - properties: - Name: - type: "string" - Protocol: - type: "string" - enum: - - "tcp" - - "udp" - - "sctp" - TargetPort: - description: "The port inside the container." - type: "integer" - PublishedPort: - description: "The port on the swarm hosts." - type: "integer" - PublishMode: - description: | - The mode in which port is published. - -


- - - "ingress" makes the target port accessible on every node, - regardless of whether there is a task for the service running on - that node or not. - - "host" bypasses the routing mesh and publish the port directly on - the swarm node where that service is running. - - type: "string" - enum: - - "ingress" - - "host" - default: "ingress" - example: "ingress" - - EndpointSpec: - description: "Properties that can be configured to access and load balance a service." - type: "object" - properties: - Mode: - description: | - The mode of resolution to use for internal load balancing between tasks. - type: "string" - enum: - - "vip" - - "dnsrr" - default: "vip" - Ports: - description: | - List of exposed ports that this service is accessible on from the - outside. Ports can only be provided if `vip` resolution mode is used. - type: "array" - items: - $ref: "#/definitions/EndpointPortConfig" - - Service: - type: "object" - properties: - ID: - type: "string" - Version: - $ref: "#/definitions/ObjectVersion" - CreatedAt: - type: "string" - format: "dateTime" - UpdatedAt: - type: "string" - format: "dateTime" - Spec: - $ref: "#/definitions/ServiceSpec" - Endpoint: - type: "object" - properties: - Spec: - $ref: "#/definitions/EndpointSpec" - Ports: - type: "array" - items: - $ref: "#/definitions/EndpointPortConfig" - VirtualIPs: - type: "array" - items: - type: "object" - properties: - NetworkID: - type: "string" - Addr: - type: "string" - UpdateStatus: - description: "The status of a service update." - type: "object" - properties: - State: - type: "string" - enum: - - "updating" - - "paused" - - "completed" - StartedAt: - type: "string" - format: "dateTime" - CompletedAt: - type: "string" - format: "dateTime" - Message: - type: "string" - ServiceStatus: - description: | - The status of the service's tasks. Provided only when requested as - part of a ServiceList operation. - type: "object" - properties: - RunningTasks: - description: | - The number of tasks for the service currently in the Running state. - type: "integer" - format: "uint64" - example: 7 - DesiredTasks: - description: | - The number of tasks for the service desired to be running. - For replicated services, this is the replica count from the - service spec. For global services, this is computed by taking - count of all tasks for the service with a Desired State other - than Shutdown. - type: "integer" - format: "uint64" - example: 10 - CompletedTasks: - description: | - The number of tasks for a job that are in the Completed state. - This field must be cross-referenced with the service type, as the - value of 0 may mean the service is not in a job mode, or it may - mean the job-mode service has no tasks yet Completed. - type: "integer" - format: "uint64" - JobStatus: - description: | - The status of the service when it is in one of ReplicatedJob or - GlobalJob modes. Absent on Replicated and Global mode services. The - JobIteration is an ObjectVersion, but unlike the Service's version, - does not need to be sent with an update request. - type: "object" - properties: - JobIteration: - description: | - JobIteration is a value increased each time a Job is executed, - successfully or otherwise. "Executed", in this case, means the - job as a whole has been started, not that an individual Task has - been launched. A job is "Executed" when its ServiceSpec is - updated. JobIteration can be used to disambiguate Tasks belonging - to different executions of a job. Though JobIteration will - increase with each subsequent execution, it may not necessarily - increase by 1, and so JobIteration should not be used to - $ref: "#/definitions/ObjectVersion" - LastExecution: - description: | - The last time, as observed by the server, that this job was - started. - type: "string" - format: "dateTime" - example: - ID: "9mnpnzenvg8p8tdbtq4wvbkcz" - Version: - Index: 19 - CreatedAt: "2016-06-07T21:05:51.880065305Z" - UpdatedAt: "2016-06-07T21:07:29.962229872Z" - Spec: - Name: "hopeful_cori" - TaskTemplate: - ContainerSpec: - Image: "redis" - Resources: - Limits: {} - Reservations: {} - RestartPolicy: - Condition: "any" - MaxAttempts: 0 - Placement: {} - ForceUpdate: 0 - Mode: - Replicated: - Replicas: 1 - UpdateConfig: - Parallelism: 1 - Delay: 1000000000 - FailureAction: "pause" - Monitor: 15000000000 - MaxFailureRatio: 0.15 - RollbackConfig: - Parallelism: 1 - Delay: 1000000000 - FailureAction: "pause" - Monitor: 15000000000 - MaxFailureRatio: 0.15 - EndpointSpec: - Mode: "vip" - Ports: - - - Protocol: "tcp" - TargetPort: 6379 - PublishedPort: 30001 - Endpoint: - Spec: - Mode: "vip" - Ports: - - - Protocol: "tcp" - TargetPort: 6379 - PublishedPort: 30001 - Ports: - - - Protocol: "tcp" - TargetPort: 6379 - PublishedPort: 30001 - VirtualIPs: - - - NetworkID: "4qvuz4ko70xaltuqbt8956gd1" - Addr: "10.255.0.2/16" - - - NetworkID: "4qvuz4ko70xaltuqbt8956gd1" - Addr: "10.255.0.3/16" - - ImageDeleteResponseItem: - type: "object" - properties: - Untagged: - description: "The image ID of an image that was untagged" - type: "string" - Deleted: - description: "The image ID of an image that was deleted" - type: "string" - - ServiceUpdateResponse: - type: "object" - properties: - Warnings: - description: "Optional warning messages" - type: "array" - items: - type: "string" - example: - Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found" - - ContainerSummary: - type: "array" - items: - type: "object" - properties: - Id: - description: "The ID of this container" - type: "string" - x-go-name: "ID" - Names: - description: "The names that this container has been given" - type: "array" - items: - type: "string" - Image: - description: "The name of the image used when creating this container" - type: "string" - ImageID: - description: "The ID of the image that this container was created from" - type: "string" - Command: - description: "Command to run when starting the container" - type: "string" - Created: - description: "When the container was created" - type: "integer" - format: "int64" - Ports: - description: "The ports exposed by this container" - type: "array" - items: - $ref: "#/definitions/Port" - 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" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - State: - description: "The state of this container (e.g. `Exited`)" - type: "string" - Status: - description: "Additional human-readable status of this container (e.g. `Exit 0`)" - type: "string" - HostConfig: - type: "object" - properties: - NetworkMode: - type: "string" - NetworkSettings: - description: "A summary of the container's network settings" - type: "object" - properties: - Networks: - type: "object" - additionalProperties: - $ref: "#/definitions/EndpointSettings" - Mounts: - type: "array" - items: - $ref: "#/definitions/Mount" - - Driver: - description: "Driver represents a driver (network, logging, secrets)." - type: "object" - required: [Name] - properties: - Name: - description: "Name of the driver." - type: "string" - x-nullable: false - example: "some-driver" - Options: - description: "Key/value map of driver-specific options." - type: "object" - x-nullable: false - additionalProperties: - type: "string" - example: - OptionA: "value for driver-specific option A" - OptionB: "value for driver-specific option B" - - SecretSpec: - type: "object" - properties: - Name: - description: "User-defined name of the secret." - type: "string" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - example: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" - Data: - description: | - Base64-url-safe-encoded ([RFC 4648](https://tools.ietf.org/html/rfc4648#section-5)) - data to store as secret. - - This field is only used to _create_ a secret, and is not returned by - other endpoints. - type: "string" - example: "" - Driver: - description: | - Name of the secrets driver used to fetch the secret's value from an - external secret store. - $ref: "#/definitions/Driver" - Templating: - description: | - Templating driver, if applicable - - Templating controls whether and how to evaluate the config payload as - a template. If no driver is set, no templating is used. - $ref: "#/definitions/Driver" - - Secret: - type: "object" - properties: - ID: - type: "string" - example: "blt1owaxmitz71s9v5zh81zun" - Version: - $ref: "#/definitions/ObjectVersion" - CreatedAt: - type: "string" - format: "dateTime" - example: "2017-07-20T13:55:28.678958722Z" - UpdatedAt: - type: "string" - format: "dateTime" - example: "2017-07-20T13:55:28.678958722Z" - Spec: - $ref: "#/definitions/SecretSpec" - - ConfigSpec: - type: "object" - properties: - Name: - description: "User-defined name of the config." - type: "string" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - Data: - description: | - Base64-url-safe-encoded ([RFC 4648](https://tools.ietf.org/html/rfc4648#section-5)) - config data. - type: "string" - Templating: - description: | - Templating driver, if applicable - - Templating controls whether and how to evaluate the config payload as - a template. If no driver is set, no templating is used. - $ref: "#/definitions/Driver" - - Config: - type: "object" - properties: - ID: - type: "string" - Version: - $ref: "#/definitions/ObjectVersion" - CreatedAt: - type: "string" - format: "dateTime" - UpdatedAt: - type: "string" - format: "dateTime" - Spec: - $ref: "#/definitions/ConfigSpec" - - ContainerState: - description: | - ContainerState stores container's running state. It's part of ContainerJSONBase - and will be returned by the "inspect" command. - type: "object" - properties: - Status: - description: | - String representation of the container state. Can be one of "created", - "running", "paused", "restarting", "removing", "exited", or "dead". - type: "string" - enum: ["created", "running", "paused", "restarting", "removing", "exited", "dead"] - example: "running" - Running: - description: | - Whether this container is running. - - Note that a running container can be _paused_. The `Running` and `Paused` - booleans are not mutually exclusive: - - When pausing a container (on Linux), the freezer cgroup is used to suspend - all processes in the container. Freezing the process requires the process to - be running. As a result, paused containers are both `Running` _and_ `Paused`. - - Use the `Status` field instead to determine if a container's state is "running". - type: "boolean" - example: true - Paused: - description: "Whether this container is paused." - type: "boolean" - example: false - Restarting: - description: "Whether this container is restarting." - type: "boolean" - example: false - OOMKilled: - description: | - Whether this container has been killed because it ran out of memory. - type: "boolean" - example: false - Dead: - type: "boolean" - example: false - Pid: - description: "The process ID of this container" - type: "integer" - example: 1234 - ExitCode: - description: "The last exit code of this container" - type: "integer" - example: 0 - Error: - type: "string" - StartedAt: - description: "The time when this container was last started." - type: "string" - example: "2020-01-06T09:06:59.461876391Z" - FinishedAt: - description: "The time when this container last exited." - type: "string" - example: "2020-01-06T09:07:59.461876391Z" - Health: - x-nullable: true - $ref: "#/definitions/Health" - - 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" - Version: - description: | - Version of the component - type: "string" - x-nullable: false - example: "19.03.12" - Details: - description: | - Key/value pairs of strings with additional information about the - component. These values are intended for informational purposes - only, and their content is not defined, and not part of the API - specification. - - These messages can be printed by the client as information to the user. - type: "object" - x-nullable: true - Version: - description: "The version of the daemon" - type: "string" - example: "19.03.12" - ApiVersion: - description: | - The default (and highest) API version that is supported by the daemon - type: "string" - example: "1.40" - MinAPIVersion: - description: | - The minimum API version that is supported by the daemon - type: "string" - example: "1.12" - GitCommit: - description: | - The Git commit of the source code that was used to build the daemon - type: "string" - example: "48a66213fe" - GoVersion: - description: | - The version Go used to compile the daemon, and the version of the Go - runtime in use. - type: "string" - example: "go1.13.14" - Os: - description: | - The operating system that the daemon is running on ("linux" or "windows") - type: "string" - example: "linux" - Arch: - description: | - The architecture that the daemon is running on - type: "string" - example: "amd64" - KernelVersion: - description: | - The kernel version (`uname -r`) that the daemon is running on. - - This field is omitted when empty. - type: "string" - example: "4.19.76-linuxkit" - Experimental: - description: | - Indicates if the daemon is started with experimental features enabled. - - This field is omitted when empty / false. - type: "boolean" - example: true - BuildTime: - description: | - The date and time that the daemon was compiled. - type: "string" - example: "2020-06-22T15:49:27.000000000+00:00" - - - SystemInfo: - type: "object" - properties: - ID: - description: | - Unique identifier of the daemon. - -


- - > **Note**: The format of the ID itself is not part of the API, and - > should not be considered stable. - type: "string" - example: "7TRN:IPZB:QYBB:VPBQ:UMPP:KARE:6ZNR:XE6T:7EWV:PKF4:ZOJD:TPYS" - Containers: - description: "Total number of containers on the host." - type: "integer" - example: 14 - ContainersRunning: - description: | - Number of containers with status `"running"`. - type: "integer" - example: 3 - ContainersPaused: - description: | - Number of containers with status `"paused"`. - type: "integer" - example: 1 - ContainersStopped: - description: | - Number of containers with status `"stopped"`. - type: "integer" - example: 10 - Images: - description: | - Total number of images on the host. - - Both _tagged_ and _untagged_ (dangling) images are counted. - type: "integer" - example: 508 - Driver: - description: "Name of the storage driver in use." - type: "string" - example: "overlay2" - DriverStatus: - description: | - Information specific to the storage driver, provided as - "label" / "value" pairs. - - This information is provided by the storage driver, and formatted - in a way consistent with the output of `docker info` on the command - line. - -


- - > **Note**: The information returned in this field, including the - > formatting of values and labels, should not be considered stable, - > and may change without notice. - type: "array" - items: - type: "array" - items: - type: "string" - example: - - ["Backing Filesystem", "extfs"] - - ["Supports d_type", "true"] - - ["Native Overlay Diff", "true"] - DockerRootDir: - description: | - Root directory of persistent Docker state. - - Defaults to `/var/lib/docker` on Linux, and `C:\ProgramData\docker` - on Windows. - type: "string" - example: "/var/lib/docker" - Plugins: - $ref: "#/definitions/PluginsInfo" - MemoryLimit: - description: "Indicates if the host has memory limit support enabled." - type: "boolean" - example: true - SwapLimit: - description: "Indicates if the host has memory swap limit support enabled." - type: "boolean" - example: true - KernelMemory: - description: | - Indicates if the host has kernel memory limit support enabled. - -


- - > **Deprecated**: This field is deprecated as the kernel 5.4 deprecated - > `kmem.limit_in_bytes`. - type: "boolean" - example: true - CpuCfsPeriod: - description: | - Indicates if CPU CFS(Completely Fair Scheduler) period is supported by - the host. - type: "boolean" - example: true - CpuCfsQuota: - description: | - Indicates if CPU CFS(Completely Fair Scheduler) quota is supported by - the host. - type: "boolean" - example: true - CPUShares: - description: | - Indicates if CPU Shares limiting is supported by the host. - type: "boolean" - example: true - CPUSet: - description: | - Indicates if CPUsets (cpuset.cpus, cpuset.mems) are supported by the host. - - See [cpuset(7)](https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt) - type: "boolean" - example: true - PidsLimit: - description: "Indicates if the host kernel has PID limit support enabled." - type: "boolean" - example: true - OomKillDisable: - description: "Indicates if OOM killer disable is supported on the host." - type: "boolean" - IPv4Forwarding: - description: "Indicates IPv4 forwarding is enabled." - type: "boolean" - example: true - BridgeNfIptables: - description: "Indicates if `bridge-nf-call-iptables` is available on the host." - type: "boolean" - example: true - BridgeNfIp6tables: - description: "Indicates if `bridge-nf-call-ip6tables` is available on the host." - type: "boolean" - example: true - Debug: - description: | - Indicates if the daemon is running in debug-mode / with debug-level - logging enabled. - type: "boolean" - example: true - NFd: - description: | - The total number of file Descriptors in use by the daemon process. - - This information is only returned if debug-mode is enabled. - type: "integer" - example: 64 - NGoroutines: - description: | - The number of goroutines that currently exist. - - This information is only returned if debug-mode is enabled. - type: "integer" - example: 174 - SystemTime: - description: | - Current system-time in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) - format with nano-seconds. - type: "string" - example: "2017-08-08T20:28:29.06202363Z" - LoggingDriver: - description: | - The logging driver to use as a default for new containers. - type: "string" - CgroupDriver: - description: | - The driver to use for managing cgroups. - type: "string" - enum: ["cgroupfs", "systemd", "none"] - default: "cgroupfs" - example: "cgroupfs" - CgroupVersion: - description: | - The version of the cgroup. - type: "string" - enum: ["1", "2"] - default: "1" - example: "1" - NEventsListener: - description: "Number of event listeners subscribed." - type: "integer" - example: 30 - KernelVersion: - description: | - Kernel version of the host. - - On Linux, this information obtained from `uname`. On Windows this - information is queried from the HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ - registry value, for example _"10.0 14393 (14393.1198.amd64fre.rs1_release_sec.170427-1353)"_. - type: "string" - example: "4.9.38-moby" - OperatingSystem: - description: | - Name of the host's operating system, for example: "Ubuntu 16.04.2 LTS" - or "Windows Server 2016 Datacenter" - type: "string" - example: "Alpine Linux v3.5" - OSVersion: - description: | - Version of the host's operating system - -


- - > **Note**: The information returned in this field, including its - > very existence, and the formatting of values, should not be considered - > stable, and may change without notice. - type: "string" - example: "16.04" - OSType: - description: | - Generic type of the operating system of the host, as returned by the - Go runtime (`GOOS`). - - Currently returned values are "linux" and "windows". A full list of - possible values can be found in the [Go documentation](https://golang.org/doc/install/source#environment). - type: "string" - example: "linux" - Architecture: - description: | - Hardware architecture of the host, as returned by the Go runtime - (`GOARCH`). - - A full list of possible values can be found in the [Go documentation](https://golang.org/doc/install/source#environment). - type: "string" - example: "x86_64" - NCPU: - description: | - The number of logical CPUs usable by the daemon. - - The number of available CPUs is checked by querying the operating - system when the daemon starts. Changes to operating system CPU - allocation after the daemon is started are not reflected. - type: "integer" - example: 4 - MemTotal: - description: | - Total amount of physical memory available on the host, in bytes. - type: "integer" - format: "int64" - example: 2095882240 - - IndexServerAddress: - description: | - Address / URL of the index server that is used for image search, - and as a default for user authentication for Docker Hub and Docker Cloud. - default: "https://index.docker.io/v1/" - type: "string" - example: "https://index.docker.io/v1/" - RegistryConfig: - $ref: "#/definitions/RegistryServiceConfig" - GenericResources: - $ref: "#/definitions/GenericResources" - HttpProxy: - description: | - HTTP-proxy configured for the daemon. This value is obtained from the - [`HTTP_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable. - Credentials ([user info component](https://tools.ietf.org/html/rfc3986#section-3.2.1)) in the proxy URL - are masked in the API response. - - Containers do not automatically inherit this configuration. - type: "string" - example: "http://xxxxx:xxxxx@proxy.corp.example.com:8080" - HttpsProxy: - description: | - HTTPS-proxy configured for the daemon. This value is obtained from the - [`HTTPS_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable. - Credentials ([user info component](https://tools.ietf.org/html/rfc3986#section-3.2.1)) in the proxy URL - are masked in the API response. - - Containers do not automatically inherit this configuration. - type: "string" - example: "https://xxxxx:xxxxx@proxy.corp.example.com:4443" - NoProxy: - description: | - Comma-separated list of domain extensions for which no proxy should be - used. This value is obtained from the [`NO_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) - environment variable. - - Containers do not automatically inherit this configuration. - type: "string" - example: "*.local, 169.254/16" - Name: - description: "Hostname of the host." - type: "string" - example: "node5.corp.example.com" - Labels: - description: | - User-defined labels (key/value metadata) as set on the daemon. - -


- - > **Note**: When part of a Swarm, nodes can both have _daemon_ labels, - > set through the daemon configuration, and _node_ labels, set from a - > manager node in the Swarm. Node labels are not included in this - > field. Node labels can be retrieved using the `/nodes/(id)` endpoint - > on a manager node in the Swarm. - type: "array" - items: - type: "string" - example: ["storage=ssd", "production"] - ExperimentalBuild: - description: | - Indicates if experimental features are enabled on the daemon. - type: "boolean" - example: true - ServerVersion: - description: | - Version string of the daemon. - - > **Note**: the [standalone Swarm API](https://docs.docker.com/swarm/swarm-api/) - > returns the Swarm version instead of the daemon version, for example - > `swarm/1.2.8`. - type: "string" - example: "17.06.0-ce" - ClusterStore: - description: | - URL of the distributed storage backend. - - - The storage backend is used for multihost networking (to store - network and endpoint information) and by the node discovery mechanism. - -


- - > **Deprecated**: This field is only propagated when using standalone Swarm - > mode, and overlay networking using an external k/v store. Overlay - > networks with Swarm mode enabled use the built-in raft store, and - > this field will be empty. - type: "string" - example: "consul://consul.corp.example.com:8600/some/path" - ClusterAdvertise: - description: | - The network endpoint that the Engine advertises for the purpose of - node discovery. ClusterAdvertise is a `host:port` combination on which - the daemon is reachable by other hosts. - -


- - > **Deprecated**: This field is only propagated when using standalone Swarm - > mode, and overlay networking using an external k/v store. Overlay - > networks with Swarm mode enabled use the built-in raft store, and - > this field will be empty. - type: "string" - example: "node5.corp.example.com:8000" - Runtimes: - description: | - List of [OCI compliant](https://github.com/opencontainers/runtime-spec) - runtimes configured on the daemon. Keys hold the "name" used to - reference the runtime. - - The Docker daemon relies on an OCI compliant runtime (invoked via the - `containerd` daemon) as its interface to the Linux kernel namespaces, - cgroups, and SELinux. - - The default runtime is `runc`, and automatically configured. Additional - runtimes can be configured by the user and will be listed here. - type: "object" - additionalProperties: - $ref: "#/definitions/Runtime" - default: - runc: - path: "runc" - example: - runc: - path: "runc" - runc-master: - path: "/go/bin/runc" - custom: - path: "/usr/local/bin/my-oci-runtime" - runtimeArgs: ["--debug", "--systemd-cgroup=false"] - DefaultRuntime: - description: | - Name of the default OCI runtime that is used when starting containers. - - The default can be overridden per-container at create time. - type: "string" - default: "runc" - example: "runc" - Swarm: - $ref: "#/definitions/SwarmInfo" - LiveRestoreEnabled: - description: | - Indicates if live restore is enabled. - - If enabled, containers are kept running when the daemon is shutdown - or upon daemon start if running containers are detected. - type: "boolean" - default: false - example: false - Isolation: - description: | - Represents the isolation technology to use as a default for containers. - The supported values are platform-specific. - - If no isolation value is specified on daemon start, on Windows client, - the default is `hyperv`, and on Windows server, the default is `process`. - - This option is currently not used on other platforms. - default: "default" - type: "string" - enum: - - "default" - - "hyperv" - - "process" - InitBinary: - description: | - Name and, optional, path of the `docker-init` binary. - - If the path is omitted, the daemon searches the host's `$PATH` for the - binary and uses the first result. - type: "string" - example: "docker-init" - ContainerdCommit: - $ref: "#/definitions/Commit" - RuncCommit: - $ref: "#/definitions/Commit" - InitCommit: - $ref: "#/definitions/Commit" - SecurityOptions: - description: | - List of security features that are enabled on the daemon, such as - apparmor, seccomp, SELinux, user-namespaces (userns), and rootless. - - Additional configuration options for each security feature may - be present, and are included as a comma-separated list of key/value - pairs. - type: "array" - items: - type: "string" - example: - - "name=apparmor" - - "name=seccomp,profile=default" - - "name=selinux" - - "name=userns" - - "name=rootless" - ProductLicense: - description: | - Reports a summary of the product license on the daemon. - - If a commercial license has been applied to the daemon, information - such as number of nodes, and expiration are included. - type: "string" - example: "Community Engine" - DefaultAddressPools: - description: | - List of custom default address pools for local networks, which can be - specified in the daemon.json file or dockerd option. - - Example: a Base "10.10.0.0/16" with Size 24 will define the set of 256 - 10.10.[0-255].0/24 address pools. - type: "array" - items: - type: "object" - properties: - Base: - description: "The network address in CIDR format" - type: "string" - example: "10.10.0.0/16" - Size: - description: "The network pool size" - type: "integer" - example: "24" - Warnings: - description: | - List of warnings / informational messages about missing features, or - issues related to the daemon configuration. - - These messages can be printed by the client as information to the user. - type: "array" - items: - type: "string" - example: - - "WARNING: No memory limit support" - - "WARNING: bridge-nf-call-iptables is disabled" - - "WARNING: bridge-nf-call-ip6tables is disabled" - - - # PluginsInfo is a temp struct holding Plugins name - # registered with docker daemon. It is used by Info struct - PluginsInfo: - description: | - Available plugins per type. - -


- - > **Note**: Only unmanaged (V1) plugins are included in this list. - > V1 plugins are "lazily" loaded, and are not returned in this list - > if there is no resource using the plugin. - type: "object" - properties: - Volume: - description: "Names of available volume-drivers, and network-driver plugins." - type: "array" - items: - type: "string" - example: ["local"] - Network: - description: "Names of available network-drivers, and network-driver plugins." - type: "array" - items: - type: "string" - example: ["bridge", "host", "ipvlan", "macvlan", "null", "overlay"] - Authorization: - description: "Names of available authorization plugins." - type: "array" - items: - type: "string" - example: ["img-authz-plugin", "hbm"] - Log: - description: "Names of available logging-drivers, and logging-driver plugins." - type: "array" - items: - type: "string" - example: ["awslogs", "fluentd", "gcplogs", "gelf", "journald", "json-file", "logentries", "splunk", "syslog"] - - - RegistryServiceConfig: - description: | - RegistryServiceConfig stores daemon registry services configuration. - type: "object" - x-nullable: true - properties: - AllowNondistributableArtifactsCIDRs: - description: | - 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. - - type: "array" - items: - type: "string" - example: ["::1/128", "127.0.0.0/8"] - 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. - type: "array" - items: - type: "string" - example: ["registry.internal.corp.example.com:3000", "[2001:db8:a0b:12f0::1]:443"] - InsecureRegistryCIDRs: - description: | - List of IP ranges of insecure registries, using the CIDR syntax - ([RFC 4632](https://tools.ietf.org/html/4632)). Insecure registries - 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 - insecure. All other registries are secure. Communicating with an - insecure registry is not possible if the daemon assumes that registry - is secure. - - This configuration override this behavior, insecure communication with - registries whose resolved IP address is within the subnet described by - the CIDR syntax. - - Registries can also be marked insecure by hostname. Those registries - are listed under `IndexConfigs` and have their `Secure` field set to - `false`. - - > **Warning**: Using this option can be useful when running a local - > registry, but introduces security vulnerabilities. This option - > should therefore ONLY be used for testing purposes. For increased - > security, users should add their CA to their system's list of trusted - > CAs instead of enabling this option. - type: "array" - items: - type: "string" - example: ["::1/128", "127.0.0.0/8"] - IndexConfigs: - type: "object" - additionalProperties: - $ref: "#/definitions/IndexInfo" - example: - "127.0.0.1:5000": - "Name": "127.0.0.1:5000" - "Mirrors": [] - "Secure": false - "Official": false - "[2001:db8:a0b:12f0::1]:80": - "Name": "[2001:db8:a0b:12f0::1]:80" - "Mirrors": [] - "Secure": false - "Official": false - "docker.io": - Name: "docker.io" - Mirrors: ["https://hub-mirror.corp.example.com:5000/"] - Secure: true - Official: true - "registry.internal.corp.example.com:3000": - Name: "registry.internal.corp.example.com:3000" - Mirrors: [] - Secure: false - Official: false - Mirrors: - description: | - List of registry URLs that act as a mirror for the official - (`docker.io`) registry. - - type: "array" - items: - type: "string" - example: - - "https://hub-mirror.corp.example.com:5000/" - - "https://[2001:db8:a0b:12f0::1]/" - - IndexInfo: - description: - IndexInfo contains information about a registry. - type: "object" - x-nullable: true - properties: - Name: - description: | - Name of the registry, such as "docker.io". - type: "string" - example: "docker.io" - Mirrors: - description: | - List of mirrors, expressed as URIs. - type: "array" - items: - type: "string" - example: - - "https://hub-mirror.corp.example.com:5000/" - - "https://registry-2.docker.io/" - - "https://registry-3.docker.io/" - Secure: - description: | - Indicates if the registry is part of the list of insecure - registries. - - If `false`, the registry is insecure. Insecure registries accept - un-encrypted (HTTP) and/or untrusted (HTTPS with certificates from - unknown CAs) communication. - - > **Warning**: Insecure registries can be useful when running a local - > registry. However, because its use creates security vulnerabilities - > it should ONLY be enabled for testing purposes. For increased - > security, users should add their CA to their system's list of - > trusted CAs instead of enabling this option. - type: "boolean" - example: true - Official: - description: | - Indicates whether this is an official registry (i.e., Docker Hub / docker.io) - type: "boolean" - example: true - - Runtime: - description: | - Runtime describes an [OCI compliant](https://github.com/opencontainers/runtime-spec) - runtime. - - The runtime is invoked by the daemon via the `containerd` daemon. OCI - runtimes act as an interface to the Linux kernel namespaces, cgroups, - and SELinux. - type: "object" - properties: - path: - description: | - Name and, optional, path, of the OCI executable binary. - - If the path is omitted, the daemon searches the host's `$PATH` for the - binary and uses the first result. - type: "string" - example: "/usr/local/bin/my-oci-runtime" - runtimeArgs: - description: | - List of command-line arguments to pass to the runtime when invoked. - type: "array" - x-nullable: true - items: - type: "string" - example: ["--debug", "--systemd-cgroup=false"] - - Commit: - description: | - 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: "object" - properties: - ID: - description: "Actual commit ID of external tool." - type: "string" - example: "cfb82a876ecc11b5ca0977d1733adbe58599088a" - Expected: - description: | - Commit ID of external tool expected by dockerd as set at build time. - type: "string" - example: "2d41c047c83e09a6d61d464906feb2a2f3c52aa4" - - SwarmInfo: - description: | - Represents generic information about swarm. - type: "object" - properties: - NodeID: - description: "Unique identifier of for this node in the swarm." - type: "string" - default: "" - example: "k67qz4598weg5unwwffg6z1m1" - NodeAddr: - description: | - IP address at which this node can be reached by other nodes in the - swarm. - type: "string" - default: "" - example: "10.0.0.46" - LocalNodeState: - $ref: "#/definitions/LocalNodeState" - ControlAvailable: - type: "boolean" - default: false - example: true - Error: - type: "string" - default: "" - RemoteManagers: - description: | - List of ID's and addresses of other managers in the swarm. - type: "array" - default: null - x-nullable: true - items: - $ref: "#/definitions/PeerNode" - example: - - NodeID: "71izy0goik036k48jg985xnds" - Addr: "10.0.0.158:2377" - - NodeID: "79y6h1o4gv8n120drcprv5nmc" - Addr: "10.0.0.159:2377" - - NodeID: "k67qz4598weg5unwwffg6z1m1" - Addr: "10.0.0.46:2377" - Nodes: - description: "Total number of nodes in the swarm." - type: "integer" - x-nullable: true - example: 4 - Managers: - description: "Total number of managers in the swarm." - type: "integer" - x-nullable: true - example: 3 - Cluster: - $ref: "#/definitions/ClusterInfo" - - LocalNodeState: - description: "Current local status of this node." - type: "string" - default: "" - enum: - - "" - - "inactive" - - "pending" - - "active" - - "error" - - "locked" - example: "active" - - PeerNode: - description: "Represents a peer-node in the swarm" - properties: - NodeID: - description: "Unique identifier of for this node in the swarm." - type: "string" - Addr: - description: | - IP address and ports at which this node can be reached. - type: "string" - - NetworkAttachmentConfig: - description: | - Specifies how a service should be attached to a particular network. - type: "object" - properties: - Target: - description: | - The target network for attachment. Must be a network name or ID. - type: "string" - Aliases: - description: | - Discoverable alternate names for the service on this network. - type: "array" - items: - type: "string" - DriverOpts: - description: | - Driver attachment options for the network target. - type: "object" - additionalProperties: - type: "string" - -paths: - /containers/json: - get: - summary: "List containers" - description: | - Returns a list of containers. For details on the format, see the - [inspect endpoint](#operation/ContainerInspect). - - Note that it uses a different, smaller representation of a container - than inspecting a single container. For example, the list of linked - containers is not propagated . - operationId: "ContainerList" - produces: - - "application/json" - parameters: - - name: "all" - in: "query" - description: | - Return all containers. By default, only running containers are shown. - type: "boolean" - default: false - - name: "limit" - in: "query" - description: | - Return this number of most recently created containers, including - non-running ones. - type: "integer" - - name: "size" - in: "query" - description: | - Return the size of container as fields `SizeRw` and `SizeRootFs`. - type: "boolean" - default: false - - name: "filters" - in: "query" - description: | - Filters to process on the container list, encoded as JSON (a - `map[string][]string`). For example, `{"status": ["paused"]}` will - only return paused containers. - - Available filters: - - - `ancestor`=(`[:]`, ``, or ``) - - `before`=(`` or ``) - - `expose`=(`[/]`|`/[]`) - - `exited=` containers with exit code of `` - - `health`=(`starting`|`healthy`|`unhealthy`|`none`) - - `id=` a container's ID - - `isolation=`(`default`|`process`|`hyperv`) (Windows daemon only) - - `is-task=`(`true`|`false`) - - `label=key` or `label="key=value"` of a container label - - `name=` a container's name - - `network`=(`` or ``) - - `publish`=(`[/]`|`/[]`) - - `since`=(`` or ``) - - `status=`(`created`|`restarting`|`running`|`removing`|`paused`|`exited`|`dead`) - - `volume`=(`` or ``) - type: "string" - responses: - 200: - description: "no error" - schema: - $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" - 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" - 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" - 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" - 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: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Container"] - /containers/create: - post: - summary: "Create a container" - operationId: "ContainerCreate" - consumes: - - "application/json" - - "application/octet-stream" - produces: - - "application/json" - parameters: - - name: "name" - in: "query" - description: | - Assign the specified name to the container. Must match - `/?[a-zA-Z0-9][a-zA-Z0-9_.-]+`. - type: "string" - pattern: "^/?[a-zA-Z0-9][a-zA-Z0-9_.-]+$" - - name: "body" - in: "body" - description: "Container to create" - schema: - allOf: - - $ref: "#/definitions/ContainerConfig" - - type: "object" - properties: - HostConfig: - $ref: "#/definitions/HostConfig" - NetworkingConfig: - $ref: "#/definitions/NetworkingConfig" - example: - Hostname: "" - Domainname: "" - User: "" - AttachStdin: false - AttachStdout: true - AttachStderr: true - Tty: false - OpenStdin: false - StdinOnce: false - Env: - - "FOO=bar" - - "BAZ=quux" - Cmd: - - "date" - Entrypoint: "" - Image: "ubuntu" - Labels: - com.example.vendor: "Acme" - com.example.license: "GPL" - com.example.version: "1.0" - Volumes: - /volumes/data: {} - WorkingDir: "" - NetworkDisabled: false - MacAddress: "12:34:56:78:9a:bc" - ExposedPorts: - 22/tcp: {} - StopSignal: "SIGTERM" - StopTimeout: 10 - HostConfig: - Binds: - - "/tmp:/tmp" - Links: - - "redis3:redis" - Memory: 0 - MemorySwap: 0 - MemoryReservation: 0 - KernelMemory: 0 - NanoCpus: 500000 - CpuPercent: 80 - CpuShares: 512 - CpuPeriod: 100000 - CpuRealtimePeriod: 1000000 - CpuRealtimeRuntime: 10000 - CpuQuota: 50000 - CpusetCpus: "0,1" - CpusetMems: "0,1" - MaximumIOps: 0 - MaximumIOBps: 0 - BlkioWeight: 300 - BlkioWeightDevice: - - {} - BlkioDeviceReadBps: - - {} - BlkioDeviceReadIOps: - - {} - BlkioDeviceWriteBps: - - {} - BlkioDeviceWriteIOps: - - {} - DeviceRequests: - - Driver: "nvidia" - Count: -1 - DeviceIDs": ["0", "1", "GPU-fef8089b-4820-abfc-e83e-94318197576e"] - Capabilities: [["gpu", "nvidia", "compute"]] - Options: - property1: "string" - property2: "string" - MemorySwappiness: 60 - OomKillDisable: false - OomScoreAdj: 500 - PidMode: "" - PidsLimit: 0 - PortBindings: - 22/tcp: - - HostPort: "11022" - PublishAllPorts: false - Privileged: false - ReadonlyRootfs: false - Dns: - - "8.8.8.8" - DnsOptions: - - "" - DnsSearch: - - "" - VolumesFrom: - - "parent" - - "other:ro" - CapAdd: - - "NET_ADMIN" - CapDrop: - - "MKNOD" - GroupAdd: - - "newgroup" - RestartPolicy: - Name: "" - MaximumRetryCount: 0 - AutoRemove: true - NetworkMode: "bridge" - Devices: [] - Ulimits: - - {} - LogConfig: - Type: "json-file" - Config: {} - SecurityOpt: [] - StorageOpt: {} - CgroupParent: "" - VolumeDriver: "" - ShmSize: 67108864 - NetworkingConfig: - EndpointsConfig: - isolated_nw: - IPAMConfig: - IPv4Address: "172.20.30.33" - IPv6Address: "2001:db8:abcd::3033" - LinkLocalIPs: - - "169.254.34.68" - - "fe80::3468" - Links: - - "container_1" - - "container_2" - Aliases: - - "server_x" - - "server_y" - - required: true - responses: - 201: - description: "Container created successfully" - schema: - type: "object" - title: "ContainerCreateResponse" - description: "OK response to ContainerCreate operation" - required: [Id, Warnings] - properties: - Id: - description: "The ID of the created container" - type: "string" - x-nullable: false - Warnings: - description: "Warnings encountered when creating the container" - type: "array" - x-nullable: false - items: - type: "string" - examples: - application/json: - Id: "e90e34656806" - Warnings: [] - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 409: - description: "conflict" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Container"] - /containers/{id}/json: - get: - summary: "Inspect a container" - description: "Return low-level information about a container." - operationId: "ContainerInspect" - produces: - - "application/json" - responses: - 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: - x-nullable: true - $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: "devicemapper" - 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: "" - LxcConf: [] - Memory: 0 - MemorySwap: 0 - MemoryReservation: 0 - KernelMemory: 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: "" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "size" - in: "query" - type: "boolean" - default: false - description: "Return the size of container as fields `SizeRw` and `SizeRootFs`" - tags: ["Container"] - /containers/{id}/top: - get: - summary: "List processes running inside a container" - description: | - On Unix systems, this is done by running the `ps` command. This endpoint - is not supported on Windows. - operationId: "ContainerTop" - responses: - 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" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "ps_args" - in: "query" - description: "The arguments to pass to `ps`. For example, `aux`" - type: "string" - default: "-ef" - tags: ["Container"] - /containers/{id}/logs: - get: - summary: "Get container logs" - description: | - Get `stdout` and `stderr` logs from a container. - - Note: This endpoint works only for containers with the `json-file` or - `journald` logging driver. - operationId: "ContainerLogs" - responses: - 200: - description: | - logs returned as a stream in response body. - For the stream format, [see the documentation for the attach endpoint](#operation/ContainerAttach). - Note that unlike the attach endpoint, the logs endpoint does not - upgrade the connection and does not set Content-Type. - schema: - type: "string" - format: "binary" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "follow" - in: "query" - description: "Keep connection after returning logs." - type: "boolean" - default: false - - name: "stdout" - in: "query" - description: "Return logs from `stdout`" - type: "boolean" - default: false - - name: "stderr" - in: "query" - description: "Return logs from `stderr`" - type: "boolean" - default: false - - name: "since" - in: "query" - description: "Only return logs since this time, as a UNIX timestamp" - type: "integer" - default: 0 - - name: "until" - in: "query" - description: "Only return logs before this time, as a UNIX timestamp" - type: "integer" - default: 0 - - name: "timestamps" - in: "query" - description: "Add timestamps to every log line" - type: "boolean" - default: false - - name: "tail" - in: "query" - description: | - Only return this number of log lines from the end of the logs. - Specify as an integer or `all` to output all log lines. - type: "string" - default: "all" - tags: ["Container"] - /containers/{id}/changes: - get: - summary: "Get changes on a container’s filesystem" - description: | - Returns which files in a container's filesystem have been added, deleted, - or modified. The `Kind` of modification can be one of: - - - `0`: Modified - - `1`: Added - - `2`: Deleted - operationId: "ContainerChanges" - produces: ["application/json"] - responses: - 200: - description: "The list of changes" - schema: - type: "array" - items: - type: "object" - x-go-name: "ContainerChangeResponseItem" - title: "ContainerChangeResponseItem" - description: "change item in response to ContainerChanges operation" - required: [Path, Kind] - properties: - Path: - description: "Path to file that has changed" - type: "string" - x-nullable: false - Kind: - description: "Kind of change" - type: "integer" - format: "uint8" - enum: [0, 1, 2] - x-nullable: false - examples: - application/json: - - Path: "/dev" - Kind: 0 - - Path: "/dev/kmsg" - Kind: 1 - - Path: "/test" - Kind: 1 - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - tags: ["Container"] - /containers/{id}/export: - get: - summary: "Export a container" - description: "Export the contents of a container as a tarball." - operationId: "ContainerExport" - produces: - - "application/octet-stream" - responses: - 200: - description: "no error" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - tags: ["Container"] - /containers/{id}/stats: - get: - summary: "Get container stats based on resource usage" - description: | - This endpoint returns a live stream of a container’s resource usage - statistics. - - The `precpu_stats` is the CPU statistic of the *previous* read, and is - used to calculate the CPU usage percentage. It is not an exact copy - of the `cpu_stats` field. - - If either `precpu_stats.online_cpus` or `cpu_stats.online_cpus` is - nil then for compatibility with older daemons the length of the - corresponding `cpu_usage.percpu_usage` array should be used. - - On a cgroup v2 host, the following fields are not set - * `blkio_stats`: all fields other than `io_service_bytes_recursive` - * `cpu_stats`: `cpu_usage.percpu_usage` - * `memory_stats`: `max_usage` and `failcnt` - Also, `memory_stats.stats` fields are incompatible with cgroup v1. - - To calculate the values shown by the `stats` command of the docker cli tool - the following formulas can be used: - * used_memory = `memory_stats.usage - memory_stats.stats.cache` - * available_memory = `memory_stats.limit` - * 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` - * CPU usage % = `(cpu_delta / system_cpu_delta) * number_cpus * 100.0` - operationId: "ContainerStats" - produces: ["application/json"] - responses: - 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 - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "stream" - in: "query" - description: | - Stream the output. If false, the stats will be output once and then - it will disconnect. - type: "boolean" - default: true - - name: "one-shot" - in: "query" - description: | - Only get a single stat instead of waiting for 2 cycles. Must be used - with `stream=false`. - type: "boolean" - default: false - tags: ["Container"] - /containers/{id}/resize: - post: - summary: "Resize a container TTY" - description: "Resize the TTY for a container." - operationId: "ContainerResize" - consumes: - - "application/octet-stream" - produces: - - "text/plain" - responses: - 200: - description: "no error" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "cannot resize container" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "h" - in: "query" - description: "Height of the TTY session in characters" - type: "integer" - - name: "w" - in: "query" - description: "Width of the TTY session in characters" - type: "integer" - tags: ["Container"] - /containers/{id}/start: - post: - summary: "Start a container" - operationId: "ContainerStart" - responses: - 204: - description: "no error" - 304: - description: "container already started" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "detachKeys" - in: "query" - description: | - Override the key sequence for detaching a container. Format is a - single character `[a-Z]` or `ctrl-` where `` is one - of: `a-z`, `@`, `^`, `[`, `,` or `_`. - type: "string" - tags: ["Container"] - /containers/{id}/stop: - post: - summary: "Stop a container" - operationId: "ContainerStop" - responses: - 204: - description: "no error" - 304: - description: "container already stopped" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "t" - in: "query" - description: "Number of seconds to wait before killing the container" - type: "integer" - tags: ["Container"] - /containers/{id}/restart: - post: - summary: "Restart a container" - operationId: "ContainerRestart" - responses: - 204: - description: "no error" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "t" - in: "query" - description: "Number of seconds to wait before killing the container" - type: "integer" - tags: ["Container"] - /containers/{id}/kill: - post: - summary: "Kill a container" - description: | - Send a POSIX signal to a container, defaulting to killing to the - container. - operationId: "ContainerKill" - responses: - 204: - description: "no error" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 409: - description: "container is not running" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "Container d37cde0fe4ad63c3a7252023b2f9800282894247d145cb5933ddf6e52cc03a28 is not running" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "signal" - in: "query" - description: "Signal to send to the container as an integer or string (e.g. `SIGINT`)" - type: "string" - default: "SIGKILL" - tags: ["Container"] - /containers/{id}/update: - post: - summary: "Update a container" - description: | - Change various configuration options of a container without having to - recreate it. - operationId: "ContainerUpdate" - consumes: ["application/json"] - produces: ["application/json"] - responses: - 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" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "update" - in: "body" - required: true - schema: - allOf: - - $ref: "#/definitions/Resources" - - type: "object" - properties: - RestartPolicy: - $ref: "#/definitions/RestartPolicy" - example: - BlkioWeight: 300 - CpuShares: 512 - CpuPeriod: 100000 - CpuQuota: 50000 - CpuRealtimePeriod: 1000000 - CpuRealtimeRuntime: 10000 - CpusetCpus: "0,1" - CpusetMems: "0" - Memory: 314572800 - MemorySwap: 514288000 - MemoryReservation: 209715200 - KernelMemory: 52428800 - RestartPolicy: - MaximumRetryCount: 4 - Name: "on-failure" - tags: ["Container"] - /containers/{id}/rename: - post: - summary: "Rename a container" - operationId: "ContainerRename" - responses: - 204: - description: "no error" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 409: - description: "name already in use" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "name" - in: "query" - required: true - description: "New name for the container" - type: "string" - tags: ["Container"] - /containers/{id}/pause: - post: - summary: "Pause a container" - description: | - Use the freezer cgroup to suspend all processes in a container. - - Traditionally, when suspending a process the `SIGSTOP` signal is used, - which is observable by the process being suspended. With the freezer - cgroup the process is unaware, and unable to capture, that it is being - suspended, and subsequently resumed. - operationId: "ContainerPause" - responses: - 204: - description: "no error" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - tags: ["Container"] - /containers/{id}/unpause: - post: - summary: "Unpause a container" - description: "Resume a container which has been paused." - operationId: "ContainerUnpause" - responses: - 204: - description: "no error" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - tags: ["Container"] - /containers/{id}/attach: - post: - summary: "Attach to a container" - description: | - Attach to a container to read its output or send it input. You can attach - to the same container multiple times and you can reattach to containers - that have been detached. - - Either the `stream` or `logs` parameter must be `true` for this endpoint - to do anything. - - See the [documentation for the `docker attach` command](https://docs.docker.com/engine/reference/commandline/attach/) - for more details. - - ### Hijacking - - This endpoint hijacks the HTTP connection to transport `stdin`, `stdout`, - and `stderr` on the same socket. - - This is the response from the daemon for an attach request: - - ``` - HTTP/1.1 200 OK - Content-Type: application/vnd.docker.raw-stream - - [STREAM] - ``` - - After the headers and two new lines, the TCP connection can now be used - for raw, bidirectional communication between the client and server. - - To hint potential proxies about connection hijacking, the Docker client - can also optionally send connection upgrade headers. - - For example, the client sends this request to upgrade the connection: - - ``` - POST /containers/16253994b7c4/attach?stream=1&stdout=1 HTTP/1.1 - Upgrade: tcp - Connection: Upgrade - ``` - - The Docker daemon will respond with a `101 UPGRADED` response, and will - similarly follow with the raw stream: - - ``` - HTTP/1.1 101 UPGRADED - Content-Type: application/vnd.docker.raw-stream - Connection: Upgrade - Upgrade: tcp - - [STREAM] - ``` - - ### Stream format - - When the TTY setting is disabled in [`POST /containers/create`](#operation/ContainerCreate), - the stream over the hijacked connected is multiplexed to separate out - `stdout` and `stderr`. The stream consists of a series of frames, each - containing a header and a payload. - - The header contains the information which the stream writes (`stdout` or - `stderr`). It also contains the size of the associated frame encoded in - the last four bytes (`uint32`). - - It is encoded on the first eight bytes like this: - - ```go - header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4} - ``` - - `STREAM_TYPE` can be: - - - 0: `stdin` (is written on `stdout`) - - 1: `stdout` - - 2: `stderr` - - `SIZE1, SIZE2, SIZE3, SIZE4` are the four bytes of the `uint32` size - encoded as big endian. - - Following the header is the payload, which is the specified number of - bytes of `STREAM_TYPE`. - - The simplest way to implement this protocol is the following: - - 1. Read 8 bytes. - 2. Choose `stdout` or `stderr` depending on the first byte. - 3. Extract the frame size from the last four bytes. - 4. Read the extracted size and output it on the correct output. - 5. Goto 1. - - ### Stream format when using a TTY - - When the TTY setting is enabled in [`POST /containers/create`](#operation/ContainerCreate), - the stream is not multiplexed. The data exchanged over the hijacked - connection is simply the raw data from the process PTY and client's - `stdin`. - - operationId: "ContainerAttach" - produces: - - "application/vnd.docker.raw-stream" - responses: - 101: - description: "no error, hints proxy about hijacking" - 200: - description: "no error, no upgrade header found" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "detachKeys" - in: "query" - description: | - Override the key sequence for detaching a container.Format is a single - character `[a-Z]` or `ctrl-` where `` is one of: `a-z`, - `@`, `^`, `[`, `,` or `_`. - type: "string" - - name: "logs" - in: "query" - description: | - Replay previous logs from the container. - - This is useful for attaching to a container that has started and you - want to output everything since the container started. - - If `stream` is also enabled, once all the previous output has been - returned, it will seamlessly transition into streaming current - output. - type: "boolean" - default: false - - name: "stream" - in: "query" - description: | - Stream attached streams from the time the request was made onwards. - type: "boolean" - default: false - - name: "stdin" - in: "query" - description: "Attach to `stdin`" - type: "boolean" - default: false - - name: "stdout" - in: "query" - description: "Attach to `stdout`" - type: "boolean" - default: false - - name: "stderr" - in: "query" - description: "Attach to `stderr`" - type: "boolean" - default: false - tags: ["Container"] - /containers/{id}/attach/ws: - get: - summary: "Attach to a container via a websocket" - operationId: "ContainerAttachWebsocket" - responses: - 101: - description: "no error, hints proxy about hijacking" - 200: - description: "no error, no upgrade header found" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "detachKeys" - in: "query" - description: | - Override the key sequence for detaching a container.Format is a single - character `[a-Z]` or `ctrl-` where `` is one of: `a-z`, - `@`, `^`, `[`, `,`, or `_`. - type: "string" - - name: "logs" - in: "query" - description: "Return logs" - type: "boolean" - default: false - - name: "stream" - in: "query" - description: "Return stream" - type: "boolean" - default: false - - name: "stdin" - in: "query" - description: "Attach to `stdin`" - type: "boolean" - default: false - - name: "stdout" - in: "query" - description: "Attach to `stdout`" - type: "boolean" - default: false - - name: "stderr" - in: "query" - description: "Attach to `stderr`" - type: "boolean" - default: false - tags: ["Container"] - /containers/{id}/wait: - post: - summary: "Wait for a container" - description: "Block until a container stops, then returns the exit code." - operationId: "ContainerWait" - produces: ["application/json"] - responses: - 200: - description: "The container has exit." - schema: - type: "object" - title: "ContainerWaitResponse" - description: "OK response to ContainerWait operation" - required: [StatusCode] - properties: - StatusCode: - description: "Exit code of the container" - type: "integer" - x-nullable: false - Error: - description: "container waiting error, if any" - type: "object" - properties: - Message: - description: "Details of an error" - type: "string" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "condition" - in: "query" - description: | - Wait until a container state reaches the given condition, either - 'not-running' (default), 'next-exit', or 'removed'. - type: "string" - default: "not-running" - tags: ["Container"] - /containers/{id}: - delete: - summary: "Remove a container" - operationId: "ContainerDelete" - responses: - 204: - description: "no error" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 409: - description: "conflict" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: | - You cannot remove a running container: c2ada9df5af8. Stop the - container before attempting removal or force remove - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "v" - in: "query" - description: "Remove anonymous volumes associated with the container." - type: "boolean" - default: false - - name: "force" - in: "query" - description: "If the container is running, kill it before removing it." - type: "boolean" - default: false - - name: "link" - in: "query" - description: "Remove the specified link associated with the container." - type: "boolean" - default: false - tags: ["Container"] - /containers/{id}/archive: - head: - summary: "Get information about files in a container" - description: | - A response header `X-Docker-Container-Path-Stat` is returned, containing - a base64 - encoded JSON object with some filesystem header information - about the path. - operationId: "ContainerArchiveInfo" - responses: - 200: - description: "no error" - headers: - X-Docker-Container-Path-Stat: - type: "string" - description: | - A base64 - encoded JSON object with some filesystem header - information about the path - 400: - description: "Bad parameter" - schema: - allOf: - - $ref: "#/definitions/ErrorResponse" - - type: "object" - properties: - message: - description: | - The error message. Either "must specify path parameter" - (path cannot be empty) or "not a directory" (path was - asserted to be a directory but exists as a file). - type: "string" - x-nullable: false - 404: - description: "Container or path does not exist" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "path" - in: "query" - required: true - description: "Resource in the container’s filesystem to archive." - type: "string" - tags: ["Container"] - get: - summary: "Get an archive of a filesystem resource in a container" - description: "Get a tar archive of a resource in the filesystem of container id." - operationId: "ContainerArchive" - produces: ["application/x-tar"] - responses: - 200: - description: "no error" - 400: - description: "Bad parameter" - schema: - allOf: - - $ref: "#/definitions/ErrorResponse" - - type: "object" - properties: - message: - description: | - The error message. Either "must specify path parameter" - (path cannot be empty) or "not a directory" (path was - asserted to be a directory but exists as a file). - type: "string" - x-nullable: false - 404: - description: "Container or path does not exist" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "path" - in: "query" - required: true - description: "Resource in the container’s filesystem to archive." - type: "string" - tags: ["Container"] - put: - summary: "Extract an archive of files or folders to a directory in a container" - description: "Upload a tar archive to be extracted to a path in the filesystem of container id." - operationId: "PutContainerArchive" - consumes: ["application/x-tar", "application/octet-stream"] - responses: - 200: - description: "The content was extracted successfully" - 400: - description: "Bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 403: - description: "Permission denied, the volume or container rootfs is marked as read-only." - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "No such container or path does not exist inside the container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the container" - type: "string" - - name: "path" - in: "query" - required: true - description: "Path to a directory in the container to extract the archive’s contents into. " - type: "string" - - name: "noOverwriteDirNonDir" - in: "query" - description: | - If `1`, `true`, or `True` then it will be an error if unpacking the - given content would cause an existing directory to be replaced with - a non-directory and vice versa. - type: "string" - - name: "copyUIDGID" - in: "query" - description: | - If `1`, `true`, then it will copy UID/GID maps to the dest file or - dir - type: "string" - - name: "inputStream" - in: "body" - required: true - description: | - The input stream must be a tar archive compressed with one of the - following algorithms: `identity` (no compression), `gzip`, `bzip2`, - or `xz`. - schema: - type: "string" - format: "binary" - tags: ["Container"] - /containers/prune: - post: - summary: "Delete stopped containers" - produces: - - "application/json" - operationId: "ContainerPrune" - parameters: - - name: "filters" - in: "query" - description: | - Filters to process on the prune list, encoded as JSON (a `map[string][]string`). - - Available filters: - - `until=` Prune containers created before this timestamp. The `` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time. - - `label` (`label=`, `label==`, `label!=`, or `label!==`) Prune containers with (or without, in case `label!=...` is used) the specified labels. - type: "string" - responses: - 200: - description: "No error" - schema: - type: "object" - title: "ContainerPruneResponse" - properties: - ContainersDeleted: - description: "Container IDs that were deleted" - type: "array" - items: - type: "string" - SpaceReclaimed: - description: "Disk space reclaimed in bytes" - type: "integer" - format: "int64" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Container"] - /images/json: - get: - summary: "List Images" - description: "Returns a list of images on the server. Note that it uses a different, smaller representation of an image than inspecting a single image." - operationId: "ImageList" - produces: - - "application/json" - responses: - 200: - description: "Summary image data for the images matching the query" - schema: - type: "array" - items: - $ref: "#/definitions/ImageSummary" - examples: - application/json: - - Id: "sha256:e216a057b1cb1efc11f8a268f37ef62083e70b1b38323ba252e25ac88904a7e8" - ParentId: "" - RepoTags: - - "ubuntu:12.04" - - "ubuntu:precise" - RepoDigests: - - "ubuntu@sha256:992069aee4016783df6345315302fa59681aae51a8eeb2f889dea59290f21787" - Created: 1474925151 - Size: 103579269 - VirtualSize: 103579269 - SharedSize: 0 - Labels: {} - Containers: 2 - - Id: "sha256:3e314f95dcace0f5e4fd37b10862fe8398e3c60ed36600bc0ca5fda78b087175" - ParentId: "" - RepoTags: - - "ubuntu:12.10" - - "ubuntu:quantal" - RepoDigests: - - "ubuntu@sha256:002fba3e3255af10be97ea26e476692a7ebed0bb074a9ab960b2e7a1526b15d7" - - "ubuntu@sha256:68ea0200f0b90df725d99d823905b04cf844f6039ef60c60bf3e019915017bd3" - Created: 1403128455 - Size: 172064416 - VirtualSize: 172064416 - SharedSize: 0 - Labels: {} - Containers: 5 - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "all" - in: "query" - description: "Show all images. Only images from a final layer (no children) are shown by default." - type: "boolean" - default: false - - name: "filters" - in: "query" - description: | - A JSON encoded value of the filters (a `map[string][]string`) to - process on the images list. - - Available filters: - - - `before`=(`[:]`, `` or ``) - - `dangling=true` - - `label=key` or `label="key=value"` of an image label - - `reference`=(`[:]`) - - `since`=(`[:]`, `` or ``) - type: "string" - - name: "digests" - in: "query" - description: "Show digest information as a `RepoDigests` field on each image." - type: "boolean" - default: false - tags: ["Image"] - /build: - post: - summary: "Build an image" - description: | - Build an image from a tar archive with a `Dockerfile` in it. - - The `Dockerfile` specifies how the image is built from the tar archive. It is typically in the archive's root, but can be at a different path or have a different name by specifying the `dockerfile` parameter. [See the `Dockerfile` reference for more information](https://docs.docker.com/engine/reference/builder/). - - The Docker daemon performs a preliminary validation of the `Dockerfile` before starting the build, and returns an error if the syntax is incorrect. After that, each instruction is run one-by-one until the ID of the new image is output. - - The build is canceled if the client drops the connection by quitting or being killed. - operationId: "ImageBuild" - consumes: - - "application/octet-stream" - produces: - - "application/json" - parameters: - - name: "inputStream" - in: "body" - description: "A tar archive compressed with one of the following algorithms: identity (no compression), gzip, bzip2, xz." - schema: - type: "string" - format: "binary" - - name: "dockerfile" - in: "query" - description: "Path within the build context to the `Dockerfile`. This is ignored if `remote` is specified and points to an external `Dockerfile`." - type: "string" - default: "Dockerfile" - - name: "t" - in: "query" - description: "A name and optional tag to apply to the image in the `name:tag` format. If you omit the tag the default `latest` value is assumed. You can provide several `t` parameters." - type: "string" - - name: "extrahosts" - in: "query" - description: "Extra hosts to add to /etc/hosts" - type: "string" - - name: "remote" - in: "query" - description: "A Git repository URI or HTTP/HTTPS context URI. If the URI points to a single text file, the file’s contents are placed into a file called `Dockerfile` and the image is built from that file. If the URI points to a tarball, the file is downloaded by the daemon and the contents therein used as the context for the build. If the URI points to a tarball and the `dockerfile` parameter is also specified, there must be a file with the corresponding path inside the tarball." - type: "string" - - name: "q" - in: "query" - description: "Suppress verbose build output." - type: "boolean" - default: false - - name: "nocache" - in: "query" - description: "Do not use the cache when building the image." - type: "boolean" - default: false - - name: "cachefrom" - in: "query" - description: "JSON array of images used for build cache resolution." - type: "string" - - name: "pull" - in: "query" - description: "Attempt to pull the image even if an older image exists locally." - type: "string" - - name: "rm" - in: "query" - description: "Remove intermediate containers after a successful build." - type: "boolean" - default: true - - name: "forcerm" - in: "query" - description: "Always remove intermediate containers, even upon failure." - type: "boolean" - default: false - - name: "memory" - in: "query" - description: "Set memory limit for build." - type: "integer" - - name: "memswap" - in: "query" - description: "Total memory (memory + swap). Set as `-1` to disable swap." - type: "integer" - - name: "cpushares" - in: "query" - description: "CPU shares (relative weight)." - type: "integer" - - name: "cpusetcpus" - in: "query" - description: "CPUs in which to allow execution (e.g., `0-3`, `0,1`)." - type: "string" - - name: "cpuperiod" - in: "query" - description: "The length of a CPU period in microseconds." - type: "integer" - - name: "cpuquota" - in: "query" - description: "Microseconds of CPU time that the container can get in a CPU period." - type: "integer" - - name: "buildargs" - in: "query" - description: > - JSON map of string pairs for build-time variables. Users pass these values at build-time. Docker - uses the buildargs as the environment context for commands run via the `Dockerfile` RUN - instruction, or for variable expansion in other `Dockerfile` instructions. This is not meant for - passing secret values. - - - For example, the build arg `FOO=bar` would become `{"FOO":"bar"}` in JSON. This would result in the - query parameter `buildargs={"FOO":"bar"}`. Note that `{"FOO":"bar"}` should be URI component encoded. - - - [Read more about the buildargs instruction.](https://docs.docker.com/engine/reference/builder/#arg) - type: "string" - - name: "shmsize" - in: "query" - description: "Size of `/dev/shm` in bytes. The size must be greater than 0. If omitted the system uses 64MB." - type: "integer" - - name: "squash" - in: "query" - description: "Squash the resulting images layers into a single layer. *(Experimental release only.)*" - type: "boolean" - - name: "labels" - in: "query" - description: "Arbitrary key/value labels to set on the image, as a JSON map of string pairs." - type: "string" - - name: "networkmode" - in: "query" - description: | - Sets the networking mode for the run commands during build. Supported - standard values are: `bridge`, `host`, `none`, and `container:`. - Any other value is taken as a custom network's name or ID to which this - container should connect to. - type: "string" - - name: "Content-type" - in: "header" - type: "string" - enum: - - "application/x-tar" - default: "application/x-tar" - - name: "X-Registry-Config" - in: "header" - description: | - This is a base64-encoded JSON object with auth configurations for multiple registries that a build may refer to. - - The key is a registry URL, and the value is an auth configuration object, [as described in the authentication section](#section/Authentication). For example: - - ``` - { - "docker.example.com": { - "username": "janedoe", - "password": "hunter2" - }, - "https://index.docker.io/v1/": { - "username": "mobydock", - "password": "conta1n3rize14" - } - } - ``` - - Only the registry domain name (and port if not the default 443) are required. However, for legacy reasons, the Docker Hub registry must be specified with both a `https://` prefix and a `/v1/` suffix even though Docker will prefer to use the v2 registry API. - type: "string" - - name: "platform" - in: "query" - description: "Platform in the format os[/arch[/variant]]" - type: "string" - default: "" - - name: "target" - in: "query" - description: "Target build stage" - type: "string" - default: "" - - name: "outputs" - in: "query" - description: "BuildKit output configuration" - type: "string" - default: "" - responses: - 200: - description: "no error" - 400: - description: "Bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Image"] - /build/prune: - post: - summary: "Delete builder cache" - produces: - - "application/json" - operationId: "BuildPrune" - parameters: - - name: "keep-storage" - in: "query" - description: "Amount of disk space in bytes to keep for cache" - type: "integer" - format: "int64" - - name: "all" - in: "query" - type: "boolean" - description: "Remove all types of build cache" - - name: "filters" - in: "query" - type: "string" - description: | - A JSON encoded value of the filters (a `map[string][]string`) to - process on the list of build cache objects. - - Available filters: - - - `until=`: duration relative to daemon's time, during which build cache was not used, in Go's duration format (e.g., '24h') - - `id=` - - `parent=` - - `type=` - - `description=` - - `inuse` - - `shared` - - `private` - responses: - 200: - description: "No error" - schema: - type: "object" - title: "BuildPruneResponse" - properties: - CachesDeleted: - type: "array" - items: - description: "ID of build cache object" - type: "string" - SpaceReclaimed: - description: "Disk space reclaimed in bytes" - type: "integer" - format: "int64" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Image"] - /images/create: - post: - summary: "Create an image" - description: "Create an image by either pulling it from a registry or importing it." - operationId: "ImageCreate" - consumes: - - "text/plain" - - "application/octet-stream" - produces: - - "application/json" - responses: - 200: - description: "no error" - 404: - description: "repository does not exist or no read access" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 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." - type: "string" - - name: "fromSrc" - in: "query" - description: "Source to import. The value may be a URL from which the image can be retrieved or `-` to read the image from the request body. This parameter may only be used when importing an image." - type: "string" - - name: "repo" - in: "query" - description: "Repository name given to an image when it is imported. The repo may include a tag. This parameter may only be used when importing an image." - type: "string" - - name: "tag" - in: "query" - description: "Tag or digest. If empty when pulling an image, this causes all tags for the given image to be pulled." - type: "string" - - name: "message" - in: "query" - description: "Set commit message for imported image." - type: "string" - - name: "inputImage" - in: "body" - description: "Image content if the value `-` has been specified in fromSrc query parameter" - schema: - type: "string" - required: false - - name: "X-Registry-Auth" - in: "header" - description: | - A base64url-encoded auth configuration. - - Refer to the [authentication section](#section/Authentication) for - details. - type: "string" - - name: "platform" - in: "query" - description: "Platform in the format os[/arch[/variant]]" - type: "string" - default: "" - tags: ["Image"] - /images/{name}/json: - get: - summary: "Inspect an image" - description: "Return low-level information about an image." - operationId: "ImageInspect" - produces: - - "application/json" - responses: - 200: - description: "No error" - schema: - $ref: "#/definitions/Image" - examples: - application/json: - Id: "sha256:85f05633ddc1c50679be2b16a0479ab6f7637f8884e0cfe0f4d20e1ebb3d6e7c" - Container: "cb91e48a60d01f1e27028b4fc6819f4f290b3cf12496c8176ec714d0d390984a" - Comment: "" - Os: "linux" - Architecture: "amd64" - Parent: "sha256:91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c" - ContainerConfig: - Tty: false - Hostname: "e611e15f9c9d" - Domainname: "" - AttachStdout: false - PublishService: "" - AttachStdin: false - OpenStdin: false - StdinOnce: false - NetworkDisabled: false - OnBuild: [] - Image: "91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c" - User: "" - WorkingDir: "" - MacAddress: "" - AttachStderr: false - Labels: - com.example.license: "GPL" - com.example.version: "1.0" - com.example.vendor: "Acme" - Env: - - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - Cmd: - - "/bin/sh" - - "-c" - - "#(nop) LABEL com.example.vendor=Acme com.example.license=GPL com.example.version=1.0" - DockerVersion: "1.9.0-dev" - VirtualSize: 188359297 - Size: 0 - Author: "" - Created: "2015-09-10T08:30:53.26995814Z" - GraphDriver: - Name: "aufs" - Data: {} - RepoDigests: - - "localhost:5000/test/busybox/example@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf" - RepoTags: - - "example:1.0" - - "example:latest" - - "example:stable" - Config: - Image: "91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c" - NetworkDisabled: false - OnBuild: [] - StdinOnce: false - PublishService: "" - AttachStdin: false - OpenStdin: false - Domainname: "" - AttachStdout: false - Tty: false - Hostname: "e611e15f9c9d" - Cmd: - - "/bin/bash" - Env: - - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - Labels: - com.example.vendor: "Acme" - com.example.version: "1.0" - com.example.license: "GPL" - MacAddress: "" - AttachStderr: false - WorkingDir: "" - User: "" - RootFS: - Type: "layers" - Layers: - - "sha256:1834950e52ce4d5a88a1bbd131c537f4d0e56d10ff0dd69e66be3b7dfa9df7e6" - - "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" - 404: - description: "No such image" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such image: someimage (tag: latest)" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: "Image name or id" - type: "string" - required: true - tags: ["Image"] - /images/{name}/history: - get: - summary: "Get the history of an image" - description: "Return parent layers of an image." - operationId: "ImageHistory" - produces: ["application/json"] - responses: - 200: - description: "List of image layers" - schema: - type: "array" - items: - type: "object" - x-go-name: HistoryResponseItem - title: "HistoryResponseItem" - description: "individual image layer information in response to ImageHistory operation" - required: [Id, Created, CreatedBy, Tags, Size, Comment] - properties: - Id: - type: "string" - x-nullable: false - Created: - type: "integer" - format: "int64" - x-nullable: false - CreatedBy: - type: "string" - x-nullable: false - Tags: - type: "array" - items: - type: "string" - Size: - type: "integer" - format: "int64" - x-nullable: false - Comment: - type: "string" - x-nullable: false - examples: - application/json: - - Id: "3db9c44f45209632d6050b35958829c3a2aa256d81b9a7be45b362ff85c54710" - Created: 1398108230 - CreatedBy: "/bin/sh -c #(nop) ADD file:eb15dbd63394e063b805a3c32ca7bf0266ef64676d5a6fab4801f2e81e2a5148 in /" - Tags: - - "ubuntu:lucid" - - "ubuntu:10.04" - Size: 182964289 - Comment: "" - - Id: "6cfa4d1f33fb861d4d114f43b25abd0ac737509268065cdfd69d544a59c85ab8" - Created: 1398108222 - CreatedBy: "/bin/sh -c #(nop) MAINTAINER Tianon Gravi - mkimage-debootstrap.sh -i iproute,iputils-ping,ubuntu-minimal -t lucid.tar.xz lucid http://archive.ubuntu.com/ubuntu/" - Tags: [] - Size: 0 - Comment: "" - - Id: "511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158" - Created: 1371157430 - CreatedBy: "" - Tags: - - "scratch12:latest" - - "scratch:latest" - Size: 0 - Comment: "Imported from -" - 404: - description: "No such image" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: "Image name or ID" - type: "string" - required: true - tags: ["Image"] - /images/{name}/push: - post: - summary: "Push an image" - description: | - Push an image to a registry. - - If you wish to push an image on to a private registry, that image must - already have a tag which references the registry. For example, - `registry.example.com/myimage:latest`. - - The push is cancelled if the HTTP connection is closed. - operationId: "ImagePush" - consumes: - - "application/octet-stream" - responses: - 200: - description: "No error" - 404: - description: "No such image" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: "Image name or ID." - type: "string" - required: true - - name: "tag" - in: "query" - description: "The tag to associate with the image on the registry." - type: "string" - - name: "X-Registry-Auth" - in: "header" - description: | - A base64url-encoded auth configuration. - - Refer to the [authentication section](#section/Authentication) for - details. - type: "string" - required: true - tags: ["Image"] - /images/{name}/tag: - post: - summary: "Tag an image" - description: "Tag an image so that it becomes part of a repository." - operationId: "ImageTag" - responses: - 201: - description: "No error" - 400: - description: "Bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "No such image" - schema: - $ref: "#/definitions/ErrorResponse" - 409: - description: "Conflict" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: "Image name or ID to tag." - type: "string" - required: true - - name: "repo" - in: "query" - description: "The repository to tag in. For example, `someuser/someimage`." - type: "string" - - name: "tag" - in: "query" - description: "The name of the new tag." - type: "string" - tags: ["Image"] - /images/{name}: - delete: - summary: "Remove an image" - description: | - Remove an image, along with any untagged parent images that were - referenced by that image. - - Images can't be removed if they have descendant images, are being - used by a running container or are being used by a build. - operationId: "ImageDelete" - produces: ["application/json"] - responses: - 200: - description: "The image was deleted successfully" - schema: - type: "array" - items: - $ref: "#/definitions/ImageDeleteResponseItem" - examples: - application/json: - - Untagged: "3e2f21a89f" - - Deleted: "3e2f21a89f" - - Deleted: "53b4f83ac9" - 404: - description: "No such image" - schema: - $ref: "#/definitions/ErrorResponse" - 409: - description: "Conflict" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: "Image name or ID" - type: "string" - required: true - - name: "force" - in: "query" - description: "Remove the image even if it is being used by stopped containers or has other tags" - type: "boolean" - default: false - - name: "noprune" - in: "query" - description: "Do not delete untagged parent images" - type: "boolean" - default: false - tags: ["Image"] - /images/search: - get: - summary: "Search images" - description: "Search for an image on Docker Hub." - operationId: "ImageSearch" - produces: - - "application/json" - responses: - 200: - description: "No error" - schema: - type: "array" - items: - type: "object" - title: "ImageSearchResponseItem" - properties: - description: - type: "string" - is_official: - type: "boolean" - is_automated: - type: "boolean" - name: - type: "string" - star_count: - type: "integer" - examples: - application/json: - - description: "" - is_official: false - is_automated: false - name: "wma55/u1210sshd" - star_count: 0 - - description: "" - is_official: false - is_automated: false - name: "jdswinbank/sshd" - star_count: 0 - - description: "" - is_official: false - is_automated: false - name: "vgauthier/sshd" - star_count: 0 - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "term" - in: "query" - description: "Term to search" - type: "string" - required: true - - name: "limit" - in: "query" - description: "Maximum number of results to return" - type: "integer" - - name: "filters" - in: "query" - description: | - A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters: - - - `is-automated=(true|false)` - - `is-official=(true|false)` - - `stars=` Matches images that has at least 'number' stars. - type: "string" - tags: ["Image"] - /images/prune: - post: - summary: "Delete unused images" - produces: - - "application/json" - operationId: "ImagePrune" - parameters: - - name: "filters" - in: "query" - description: | - Filters to process on the prune list, encoded as JSON (a `map[string][]string`). Available filters: - - - `dangling=` When set to `true` (or `1`), prune only - unused *and* untagged images. When set to `false` - (or `0`), all unused images are pruned. - - `until=` Prune images created before this timestamp. The `` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time. - - `label` (`label=`, `label==`, `label!=`, or `label!==`) Prune images with (or without, in case `label!=...` is used) the specified labels. - type: "string" - responses: - 200: - description: "No error" - schema: - type: "object" - title: "ImagePruneResponse" - properties: - ImagesDeleted: - description: "Images that were deleted" - type: "array" - items: - $ref: "#/definitions/ImageDeleteResponseItem" - SpaceReclaimed: - description: "Disk space reclaimed in bytes" - type: "integer" - format: "int64" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Image"] - /auth: - post: - summary: "Check auth configuration" - description: | - Validate credentials for a registry and, if available, get an identity - token for accessing the registry without password. - operationId: "SystemAuth" - consumes: ["application/json"] - produces: ["application/json"] - responses: - 200: - description: "An identity token was generated successfully." - schema: - type: "object" - title: "SystemAuthResponse" - required: [Status] - properties: - Status: - description: "The status of the authentication" - type: "string" - x-nullable: false - IdentityToken: - description: "An opaque token used to authenticate a user after a successful login" - type: "string" - x-nullable: false - examples: - application/json: - Status: "Login Succeeded" - IdentityToken: "9cbaf023786cd7..." - 204: - description: "No error" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "authConfig" - in: "body" - description: "Authentication to check" - schema: - $ref: "#/definitions/AuthConfig" - tags: ["System"] - /info: - get: - summary: "Get system information" - operationId: "SystemInfo" - produces: - - "application/json" - responses: - 200: - description: "No error" - schema: - $ref: "#/definitions/SystemInfo" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["System"] - /version: - get: - summary: "Get version" - description: "Returns the version of Docker that is running and various information about the system that Docker is running on." - operationId: "SystemVersion" - produces: ["application/json"] - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/SystemVersion" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["System"] - /_ping: - get: - summary: "Ping" - description: "This is a dummy endpoint you can use to test if the server is accessible." - operationId: "SystemPing" - produces: ["text/plain"] - responses: - 200: - description: "no error" - schema: - type: "string" - example: "OK" - headers: - API-Version: - type: "string" - description: "Max API Version the server supports" - Builder-Version: - type: "string" - description: "Default version of docker image builder" - Docker-Experimental: - type: "boolean" - description: "If the server is running with experimental mode enabled" - Cache-Control: - type: "string" - default: "no-cache, no-store, must-revalidate" - Pragma: - type: "string" - default: "no-cache" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - headers: - Cache-Control: - type: "string" - default: "no-cache, no-store, must-revalidate" - Pragma: - type: "string" - default: "no-cache" - tags: ["System"] - head: - summary: "Ping" - description: "This is a dummy endpoint you can use to test if the server is accessible." - operationId: "SystemPingHead" - produces: ["text/plain"] - responses: - 200: - description: "no error" - schema: - type: "string" - example: "(empty)" - headers: - API-Version: - type: "string" - description: "Max API Version the server supports" - Builder-Version: - type: "string" - description: "Default version of docker image builder" - Docker-Experimental: - type: "boolean" - description: "If the server is running with experimental mode enabled" - Cache-Control: - type: "string" - default: "no-cache, no-store, must-revalidate" - Pragma: - type: "string" - default: "no-cache" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["System"] - /commit: - post: - summary: "Create a new image from a container" - operationId: "ImageCommit" - consumes: - - "application/json" - produces: - - "application/json" - responses: - 201: - description: "no error" - schema: - $ref: "#/definitions/IdResponse" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "containerConfig" - in: "body" - description: "The container configuration" - schema: - $ref: "#/definitions/ContainerConfig" - - name: "container" - in: "query" - description: "The ID or name of the container to commit" - type: "string" - - name: "repo" - in: "query" - description: "Repository name for the created image" - type: "string" - - name: "tag" - in: "query" - description: "Tag name for the create image" - type: "string" - - name: "comment" - in: "query" - description: "Commit message" - type: "string" - - name: "author" - in: "query" - description: "Author of the image (e.g., `John Hannibal Smith `)" - type: "string" - - name: "pause" - in: "query" - description: "Whether to pause the container before committing" - type: "boolean" - default: true - - name: "changes" - in: "query" - description: "`Dockerfile` instructions to apply while committing" - type: "string" - tags: ["Image"] - /events: - get: - summary: "Monitor events" - description: | - Stream real-time events from the server. - - Various objects within Docker report events when something happens to them. - - Containers report these events: `attach`, `commit`, `copy`, `create`, `destroy`, `detach`, `die`, `exec_create`, `exec_detach`, `exec_start`, `exec_die`, `export`, `health_status`, `kill`, `oom`, `pause`, `rename`, `resize`, `restart`, `start`, `stop`, `top`, `unpause`, `update`, and `prune` - - Images report these events: `delete`, `import`, `load`, `pull`, `push`, `save`, `tag`, `untag`, and `prune` - - Volumes report these events: `create`, `mount`, `unmount`, `destroy`, and `prune` - - Networks report these events: `create`, `connect`, `disconnect`, `destroy`, `update`, `remove`, and `prune` - - The Docker daemon reports these events: `reload` - - Services report these events: `create`, `update`, and `remove` - - Nodes report these events: `create`, `update`, and `remove` - - Secrets report these events: `create`, `update`, and `remove` - - Configs report these events: `create`, `update`, and `remove` - - The Builder reports `prune` events - - operationId: "SystemEvents" - produces: - - "application/json" - responses: - 200: - description: "no error" - schema: - type: "object" - title: "SystemEventsResponse" - properties: - Type: - description: "The type of object emitting the event" - type: "string" - Action: - description: "The type of event" - type: "string" - Actor: - type: "object" - properties: - ID: - description: "The ID of the object emitting the event" - type: "string" - Attributes: - description: "Various key/value attributes of the object, depending on its type" - type: "object" - additionalProperties: - type: "string" - time: - description: "Timestamp of event" - type: "integer" - timeNano: - description: "Timestamp of event, with nanosecond accuracy" - type: "integer" - format: "int64" - examples: - application/json: - Type: "container" - Action: "create" - Actor: - ID: "ede54ee1afda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c743" - Attributes: - com.example.some-label: "some-label-value" - image: "alpine" - name: "my-container" - time: 1461943101 - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "since" - in: "query" - description: "Show events created since this timestamp then stream new events." - type: "string" - - name: "until" - in: "query" - description: "Show events created until this timestamp then stop streaming." - type: "string" - - name: "filters" - in: "query" - description: | - A JSON encoded value of filters (a `map[string][]string`) to process on the event list. Available filters: - - - `config=` config name or ID - - `container=` container name or ID - - `daemon=` daemon name or ID - - `event=` event type - - `image=` image name or ID - - `label=` image or container label - - `network=` network name or ID - - `node=` node ID - - `plugin`= plugin name or ID - - `scope`= local or swarm - - `secret=` secret name or ID - - `service=` service name or ID - - `type=` object to filter by, one of `container`, `image`, `volume`, `network`, `daemon`, `plugin`, `node`, `service`, `secret` or `config` - - `volume=` volume name - type: "string" - tags: ["System"] - /system/df: - get: - summary: "Get data usage information" - operationId: "SystemDataUsage" - responses: - 200: - description: "no error" - schema: - type: "object" - title: "SystemDataUsageResponse" - properties: - LayersSize: - type: "integer" - format: "int64" - Images: - type: "array" - items: - $ref: "#/definitions/ImageSummary" - Containers: - type: "array" - items: - $ref: "#/definitions/ContainerSummary" - Volumes: - type: "array" - items: - $ref: "#/definitions/Volume" - BuildCache: - type: "array" - items: - $ref: "#/definitions/BuildCache" - example: - LayersSize: 1092588 - Images: - - - Id: "sha256:2b8fd9751c4c0f5dd266fcae00707e67a2545ef34f9a29354585f93dac906749" - ParentId: "" - RepoTags: - - "busybox:latest" - RepoDigests: - - "busybox@sha256:a59906e33509d14c036c8678d687bd4eec81ed7c4b8ce907b888c607f6a1e0e6" - Created: 1466724217 - Size: 1092588 - SharedSize: 0 - VirtualSize: 1092588 - Labels: {} - Containers: 1 - Containers: - - - Id: "e575172ed11dc01bfce087fb27bee502db149e1a0fad7c296ad300bbff178148" - Names: - - "/top" - Image: "busybox" - ImageID: "sha256:2b8fd9751c4c0f5dd266fcae00707e67a2545ef34f9a29354585f93dac906749" - Command: "top" - Created: 1472592424 - Ports: [] - SizeRootFs: 1092588 - Labels: {} - State: "exited" - Status: "Exited (0) 56 minutes ago" - HostConfig: - NetworkMode: "default" - NetworkSettings: - Networks: - bridge: - IPAMConfig: null - Links: null - Aliases: null - NetworkID: "d687bc59335f0e5c9ee8193e5612e8aee000c8c62ea170cfb99c098f95899d92" - EndpointID: "8ed5115aeaad9abb174f68dcf135b49f11daf597678315231a32ca28441dec6a" - Gateway: "172.18.0.1" - IPAddress: "172.18.0.2" - IPPrefixLen: 16 - IPv6Gateway: "" - GlobalIPv6Address: "" - GlobalIPv6PrefixLen: 0 - MacAddress: "02:42:ac:12:00:02" - Mounts: [] - Volumes: - - - Name: "my-volume" - Driver: "local" - Mountpoint: "/var/lib/docker/volumes/my-volume/_data" - Labels: null - Scope: "local" - Options: null - UsageData: - Size: 10920104 - RefCount: 2 - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["System"] - /images/{name}/get: - get: - summary: "Export an image" - description: | - Get a tarball containing all images and metadata for a repository. - - If `name` is a specific name and tag (e.g. `ubuntu:latest`), then only that image (and its parents) are returned. If `name` is an image ID, similarly only that image (and its parents) are returned, but with the exclusion of the `repositories` file in the tarball, as there were no image names referenced. - - ### Image tarball format - - An image tarball contains one directory per image layer (named using its long ID), each containing these files: - - - `VERSION`: currently `1.0` - the file format version - - `json`: detailed layer information, similar to `docker inspect layer_id` - - `layer.tar`: A tarfile containing the filesystem changes in this layer - - The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions. - - If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs. - - ```json - { - "hello-world": { - "latest": "565a9d68a73f6706862bfe8409a7f659776d4d60a8d096eb4a3cbce6999cc2a1" - } - } - ``` - operationId: "ImageGet" - produces: - - "application/x-tar" - responses: - 200: - description: "no error" - schema: - type: "string" - format: "binary" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: "Image name or ID" - type: "string" - required: true - tags: ["Image"] - /images/get: - get: - summary: "Export several images" - description: | - Get a tarball containing all images and metadata for several image - repositories. - - For each value of the `names` parameter: if it is a specific name and - tag (e.g. `ubuntu:latest`), then only that image (and its parents) are - returned; if it is an image ID, similarly only that image (and its parents) - are returned and there would be no names referenced in the 'repositories' - file for this image ID. - - For details on the format, see the [export image endpoint](#operation/ImageGet). - operationId: "ImageGetAll" - produces: - - "application/x-tar" - responses: - 200: - description: "no error" - schema: - type: "string" - format: "binary" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "names" - in: "query" - description: "Image names to filter by" - type: "array" - items: - type: "string" - tags: ["Image"] - /images/load: - post: - summary: "Import images" - description: | - Load a set of images and tags into a repository. - - For details on the format, see the [export image endpoint](#operation/ImageGet). - operationId: "ImageLoad" - consumes: - - "application/x-tar" - produces: - - "application/json" - responses: - 200: - description: "no error" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "imagesTarball" - in: "body" - description: "Tar archive containing images" - schema: - type: "string" - format: "binary" - - name: "quiet" - in: "query" - description: "Suppress progress details during load." - type: "boolean" - default: false - tags: ["Image"] - /containers/{id}/exec: - post: - summary: "Create an exec instance" - description: "Run a command inside a running container." - operationId: "ContainerExec" - consumes: - - "application/json" - produces: - - "application/json" - responses: - 201: - description: "no error" - schema: - $ref: "#/definitions/IdResponse" - 404: - description: "no such container" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such container: c2ada9df5af8" - 409: - description: "container is paused" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "execConfig" - in: "body" - description: "Exec configuration" - schema: - type: "object" - properties: - AttachStdin: - type: "boolean" - description: "Attach to `stdin` of the exec command." - AttachStdout: - type: "boolean" - description: "Attach to `stdout` of the exec command." - AttachStderr: - type: "boolean" - description: "Attach to `stderr` of the exec command." - DetachKeys: - type: "string" - description: | - Override the key sequence for detaching a container. Format is - a single character `[a-Z]` or `ctrl-` where `` - is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. - Tty: - type: "boolean" - description: "Allocate a pseudo-TTY." - Env: - description: | - A list of environment variables in the form `["VAR=value", ...]`. - type: "array" - items: - type: "string" - Cmd: - type: "array" - description: "Command to run, as a string or array of strings." - items: - type: "string" - Privileged: - type: "boolean" - description: "Runs the exec process with extended privileges." - default: false - User: - type: "string" - description: | - The user, and optionally, group to run the exec process inside - the container. Format is one of: `user`, `user:group`, `uid`, - or `uid:gid`. - WorkingDir: - type: "string" - description: | - The working directory for the exec process inside the container. - example: - AttachStdin: false - AttachStdout: true - AttachStderr: true - DetachKeys: "ctrl-p,ctrl-q" - Tty: false - Cmd: - - "date" - Env: - - "FOO=bar" - - "BAZ=quux" - required: true - - name: "id" - in: "path" - description: "ID or name of container" - type: "string" - required: true - tags: ["Exec"] - /exec/{id}/start: - post: - summary: "Start an exec instance" - description: | - Starts a previously set up exec instance. If detach is true, this endpoint - returns immediately after starting the command. Otherwise, it sets up an - interactive session with the command. - operationId: "ExecStart" - consumes: - - "application/json" - produces: - - "application/vnd.docker.raw-stream" - responses: - 200: - description: "No error" - 404: - description: "No such exec instance" - schema: - $ref: "#/definitions/ErrorResponse" - 409: - description: "Container is stopped or paused" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "execStartConfig" - in: "body" - schema: - type: "object" - properties: - Detach: - type: "boolean" - description: "Detach from the command." - Tty: - type: "boolean" - description: "Allocate a pseudo-TTY." - example: - Detach: false - Tty: false - - name: "id" - in: "path" - description: "Exec instance ID" - required: true - type: "string" - tags: ["Exec"] - /exec/{id}/resize: - post: - summary: "Resize an exec instance" - description: | - Resize the TTY session used by an exec instance. This endpoint only works - if `tty` was specified as part of creating and starting the exec instance. - operationId: "ExecResize" - responses: - 201: - description: "No error" - 404: - description: "No such exec instance" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "Exec instance ID" - required: true - type: "string" - - name: "h" - in: "query" - description: "Height of the TTY session in characters" - type: "integer" - - name: "w" - in: "query" - description: "Width of the TTY session in characters" - type: "integer" - tags: ["Exec"] - /exec/{id}/json: - get: - summary: "Inspect an exec instance" - description: "Return low-level information about an exec instance." - operationId: "ExecInspect" - produces: - - "application/json" - responses: - 200: - description: "No error" - schema: - type: "object" - title: "ExecInspectResponse" - properties: - CanRemove: - type: "boolean" - DetachKeys: - type: "string" - ID: - type: "string" - Running: - type: "boolean" - ExitCode: - type: "integer" - ProcessConfig: - $ref: "#/definitions/ProcessConfig" - OpenStdin: - type: "boolean" - OpenStderr: - type: "boolean" - OpenStdout: - type: "boolean" - ContainerID: - type: "string" - Pid: - type: "integer" - description: "The system process ID for the exec process." - examples: - application/json: - CanRemove: false - ContainerID: "b53ee82b53a40c7dca428523e34f741f3abc51d9f297a14ff874bf761b995126" - DetachKeys: "" - ExitCode: 2 - ID: "f33bbfb39f5b142420f4759b2348913bd4a8d1a6d7fd56499cb41a1bb91d7b3b" - OpenStderr: true - OpenStdin: true - OpenStdout: true - ProcessConfig: - arguments: - - "-c" - - "exit 2" - entrypoint: "sh" - privileged: false - tty: true - user: "1000" - Running: false - Pid: 42000 - 404: - description: "No such exec instance" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "Exec instance ID" - required: true - type: "string" - tags: ["Exec"] - - /volumes: - get: - summary: "List volumes" - operationId: "VolumeList" - produces: ["application/json"] - responses: - 200: - description: "Summary volume data that matches the query" - schema: - type: "object" - title: "VolumeListResponse" - description: "Volume list response" - required: [Volumes, Warnings] - properties: - Volumes: - type: "array" - x-nullable: false - description: "List of volumes" - items: - $ref: "#/definitions/Volume" - Warnings: - type: "array" - x-nullable: false - description: | - Warnings that occurred when fetching the list of volumes. - items: - type: "string" - - examples: - application/json: - Volumes: - - CreatedAt: "2017-07-19T12:00:26Z" - Name: "tardis" - Driver: "local" - Mountpoint: "/var/lib/docker/volumes/tardis" - Labels: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" - Scope: "local" - Options: - device: "tmpfs" - o: "size=100m,uid=1000" - type: "tmpfs" - Warnings: [] - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "filters" - in: "query" - description: | - JSON encoded value of the filters (a `map[string][]string`) to - process on the volumes list. Available filters: - - - `dangling=` When set to `true` (or `1`), returns all - volumes that are not in use by a container. When set to `false` - (or `0`), only volumes that are in use by one or more - containers are returned. - - `driver=` Matches volumes based on their driver. - - `label=` or `label=:` Matches volumes based on - the presence of a `label` alone or a `label` and a value. - - `name=` Matches all or part of a volume name. - type: "string" - format: "json" - tags: ["Volume"] - - /volumes/create: - post: - summary: "Create a volume" - operationId: "VolumeCreate" - consumes: ["application/json"] - produces: ["application/json"] - responses: - 201: - description: "The volume was created successfully" - schema: - $ref: "#/definitions/Volume" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "volumeConfig" - in: "body" - required: true - description: "Volume configuration" - schema: - type: "object" - description: "Volume configuration" - title: "VolumeConfig" - properties: - Name: - description: | - The new volume's name. If not specified, Docker generates a name. - type: "string" - x-nullable: false - Driver: - description: "Name of the volume driver to use." - type: "string" - default: "local" - x-nullable: false - DriverOpts: - description: | - A mapping of driver options and values. These options are - passed directly to the driver and are driver specific. - type: "object" - additionalProperties: - type: "string" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - example: - Name: "tardis" - Labels: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" - Driver: "custom" - tags: ["Volume"] - - /volumes/{name}: - get: - summary: "Inspect a volume" - operationId: "VolumeInspect" - produces: ["application/json"] - responses: - 200: - description: "No error" - schema: - $ref: "#/definitions/Volume" - 404: - description: "No such volume" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - required: true - description: "Volume name or ID" - type: "string" - tags: ["Volume"] - - delete: - summary: "Remove a volume" - description: "Instruct the driver to remove the volume." - operationId: "VolumeDelete" - responses: - 204: - description: "The volume was removed" - 404: - description: "No such volume or volume driver" - schema: - $ref: "#/definitions/ErrorResponse" - 409: - description: "Volume is in use and cannot be removed" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - required: true - description: "Volume name or ID" - type: "string" - - name: "force" - in: "query" - description: "Force the removal of the volume" - type: "boolean" - default: false - tags: ["Volume"] - /volumes/prune: - post: - summary: "Delete unused volumes" - produces: - - "application/json" - operationId: "VolumePrune" - parameters: - - name: "filters" - in: "query" - description: | - Filters to process on the prune list, encoded as JSON (a `map[string][]string`). - - Available filters: - - `label` (`label=`, `label==`, `label!=`, or `label!==`) Prune volumes with (or without, in case `label!=...` is used) the specified labels. - type: "string" - responses: - 200: - description: "No error" - schema: - type: "object" - title: "VolumePruneResponse" - properties: - VolumesDeleted: - description: "Volumes that were deleted" - type: "array" - items: - type: "string" - SpaceReclaimed: - description: "Disk space reclaimed in bytes" - type: "integer" - format: "int64" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Volume"] - /networks: - get: - summary: "List networks" - description: | - Returns a list of networks. For details on the format, see the - [network inspect endpoint](#operation/NetworkInspect). - - Note that it uses a different, smaller representation of a network than - inspecting a single network. For example, the list of containers attached - to the network is not propagated in API versions 1.28 and up. - operationId: "NetworkList" - produces: - - "application/json" - responses: - 200: - description: "No error" - schema: - type: "array" - items: - $ref: "#/definitions/Network" - examples: - application/json: - - Name: "bridge" - Id: "f2de39df4171b0dc801e8002d1d999b77256983dfc63041c0f34030aa3977566" - Created: "2016-10-19T06:21:00.416543526Z" - Scope: "local" - Driver: "bridge" - EnableIPv6: false - Internal: false - Attachable: false - Ingress: false - IPAM: - Driver: "default" - Config: - - - Subnet: "172.17.0.0/16" - Options: - com.docker.network.bridge.default_bridge: "true" - com.docker.network.bridge.enable_icc: "true" - com.docker.network.bridge.enable_ip_masquerade: "true" - com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" - com.docker.network.bridge.name: "docker0" - com.docker.network.driver.mtu: "1500" - - Name: "none" - Id: "e086a3893b05ab69242d3c44e49483a3bbbd3a26b46baa8f61ab797c1088d794" - Created: "0001-01-01T00:00:00Z" - Scope: "local" - Driver: "null" - EnableIPv6: false - Internal: false - Attachable: false - Ingress: false - IPAM: - Driver: "default" - Config: [] - Containers: {} - Options: {} - - Name: "host" - Id: "13e871235c677f196c4e1ecebb9dc733b9b2d2ab589e30c539efeda84a24215e" - Created: "0001-01-01T00:00:00Z" - Scope: "local" - Driver: "host" - EnableIPv6: false - Internal: false - Attachable: false - Ingress: false - IPAM: - Driver: "default" - Config: [] - Containers: {} - Options: {} - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "filters" - in: "query" - description: | - JSON encoded value of the filters (a `map[string][]string`) to process - on the networks list. - - Available filters: - - - `dangling=` When set to `true` (or `1`), returns all - networks that are not in use by a container. When set to `false` - (or `0`), only networks that are in use by one or more - containers are returned. - - `driver=` Matches a network's driver. - - `id=` Matches all or part of a network ID. - - `label=` or `label==` of a network label. - - `name=` Matches all or part of a network name. - - `scope=["swarm"|"global"|"local"]` Filters networks by scope (`swarm`, `global`, or `local`). - - `type=["custom"|"builtin"]` Filters networks by type. The `custom` keyword returns all user-defined networks. - type: "string" - tags: ["Network"] - - /networks/{id}: - get: - summary: "Inspect a network" - operationId: "NetworkInspect" - produces: - - "application/json" - responses: - 200: - description: "No error" - schema: - $ref: "#/definitions/Network" - 404: - description: "Network not found" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "Network ID or name" - required: true - type: "string" - - name: "verbose" - in: "query" - description: "Detailed inspect output for troubleshooting" - type: "boolean" - default: false - - name: "scope" - in: "query" - description: "Filter the network by scope (swarm, global, or local)" - type: "string" - tags: ["Network"] - - delete: - summary: "Remove a network" - operationId: "NetworkDelete" - responses: - 204: - description: "No error" - 403: - description: "operation not supported for pre-defined networks" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such network" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "Network ID or name" - required: true - type: "string" - tags: ["Network"] - - /networks/create: - post: - summary: "Create a network" - operationId: "NetworkCreate" - consumes: - - "application/json" - produces: - - "application/json" - responses: - 201: - description: "No error" - schema: - type: "object" - title: "NetworkCreateResponse" - properties: - Id: - description: "The ID of the created network." - type: "string" - Warning: - type: "string" - example: - Id: "22be93d5babb089c5aab8dbc369042fad48ff791584ca2da2100db837a1c7c30" - Warning: "" - 403: - description: "operation not supported for pre-defined networks" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "plugin not found" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "networkConfig" - in: "body" - description: "Network configuration" - required: true - schema: - type: "object" - required: ["Name"] - properties: - Name: - description: "The network's name." - type: "string" - CheckDuplicate: - description: | - Check for networks with duplicate names. Since Network is - primarily keyed based on a random ID and not on the name, and - network name is strictly a user-friendly alias to the network - which is uniquely identified using ID, there is no guaranteed - way to check for duplicates. CheckDuplicate is there to provide - a best effort checking of any networks which has the same name - but it is not guaranteed to catch all name collisions. - type: "boolean" - Driver: - description: "Name of the network driver plugin to use." - type: "string" - default: "bridge" - Internal: - description: "Restrict external access to the network." - type: "boolean" - Attachable: - description: | - Globally scoped network is manually attachable by regular - containers from workers in swarm mode. - type: "boolean" - Ingress: - description: | - Ingress network is the network which provides the routing-mesh - in swarm mode. - type: "boolean" - IPAM: - description: "Optional custom IP scheme for the network." - $ref: "#/definitions/IPAM" - EnableIPv6: - description: "Enable IPv6 on the network." - type: "boolean" - Options: - description: "Network specific options to be used by the drivers." - type: "object" - additionalProperties: - type: "string" - Labels: - description: "User-defined key/value metadata." - type: "object" - additionalProperties: - type: "string" - example: - Name: "isolated_nw" - CheckDuplicate: false - Driver: "bridge" - EnableIPv6: true - IPAM: - Driver: "default" - Config: - - Subnet: "172.20.0.0/16" - IPRange: "172.20.10.0/24" - Gateway: "172.20.10.11" - - Subnet: "2001:db8:abcd::/64" - Gateway: "2001:db8:abcd::1011" - Options: - foo: "bar" - Internal: true - Attachable: false - Ingress: false - Options: - com.docker.network.bridge.default_bridge: "true" - com.docker.network.bridge.enable_icc: "true" - com.docker.network.bridge.enable_ip_masquerade: "true" - com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" - com.docker.network.bridge.name: "docker0" - com.docker.network.driver.mtu: "1500" - Labels: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" - tags: ["Network"] - - /networks/{id}/connect: - post: - summary: "Connect a container to a network" - operationId: "NetworkConnect" - consumes: - - "application/json" - responses: - 200: - description: "No error" - 403: - description: "Operation not supported for swarm scoped networks" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "Network or container not found" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "Network ID or name" - required: true - type: "string" - - name: "container" - in: "body" - required: true - schema: - type: "object" - properties: - Container: - type: "string" - description: "The ID or name of the container to connect to the network." - EndpointConfig: - $ref: "#/definitions/EndpointSettings" - example: - Container: "3613f73ba0e4" - EndpointConfig: - IPAMConfig: - IPv4Address: "172.24.56.89" - IPv6Address: "2001:db8::5689" - tags: ["Network"] - - /networks/{id}/disconnect: - post: - summary: "Disconnect a container from a network" - operationId: "NetworkDisconnect" - consumes: - - "application/json" - responses: - 200: - description: "No error" - 403: - description: "Operation not supported for swarm scoped networks" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "Network or container not found" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "Network ID or name" - required: true - type: "string" - - name: "container" - in: "body" - required: true - schema: - type: "object" - properties: - Container: - type: "string" - description: | - The ID or name of the container to disconnect from the network. - Force: - type: "boolean" - description: | - Force the container to disconnect from the network. - tags: ["Network"] - /networks/prune: - post: - summary: "Delete unused networks" - produces: - - "application/json" - operationId: "NetworkPrune" - parameters: - - name: "filters" - in: "query" - description: | - Filters to process on the prune list, encoded as JSON (a `map[string][]string`). - - Available filters: - - `until=` Prune networks created before this timestamp. The `` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time. - - `label` (`label=`, `label==`, `label!=`, or `label!==`) Prune networks with (or without, in case `label!=...` is used) the specified labels. - type: "string" - responses: - 200: - description: "No error" - schema: - type: "object" - title: "NetworkPruneResponse" - properties: - NetworksDeleted: - description: "Networks that were deleted" - type: "array" - items: - type: "string" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Network"] - /plugins: - get: - summary: "List plugins" - operationId: "PluginList" - description: "Returns information about installed plugins." - produces: ["application/json"] - responses: - 200: - description: "No error" - schema: - type: "array" - items: - $ref: "#/definitions/Plugin" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "filters" - in: "query" - type: "string" - description: | - A JSON encoded value of the filters (a `map[string][]string`) to - process on the plugin list. - - Available filters: - - - `capability=` - - `enable=|` - tags: ["Plugin"] - - /plugins/privileges: - get: - summary: "Get plugin privileges" - operationId: "GetPluginPrivileges" - responses: - 200: - description: "no error" - schema: - type: "array" - items: - description: | - Describes a permission the user has to accept upon installing - the plugin. - type: "object" - title: "PluginPrivilegeItem" - properties: - Name: - type: "string" - Description: - type: "string" - Value: - type: "array" - items: - type: "string" - example: - - Name: "network" - Description: "" - Value: - - "host" - - Name: "mount" - Description: "" - Value: - - "/data" - - Name: "device" - Description: "" - Value: - - "/dev/cpu_dma_latency" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "remote" - in: "query" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - tags: - - "Plugin" - - /plugins/pull: - post: - summary: "Install a plugin" - operationId: "PluginPull" - description: | - Pulls and installs a plugin. After the plugin is installed, it can be - enabled using the [`POST /plugins/{name}/enable` endpoint](#operation/PostPluginsEnable). - produces: - - "application/json" - responses: - 204: - description: "no error" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "remote" - in: "query" - description: | - Remote reference for plugin to install. - - The `:latest` tag is optional, and is used as the default if omitted. - required: true - type: "string" - - name: "name" - in: "query" - description: | - Local name for the pulled plugin. - - The `:latest` tag is optional, and is used as the default if omitted. - required: false - type: "string" - - name: "X-Registry-Auth" - in: "header" - description: | - A base64url-encoded auth configuration to use when pulling a plugin - from a registry. - - Refer to the [authentication section](#section/Authentication) for - details. - type: "string" - - name: "body" - in: "body" - schema: - type: "array" - items: - description: | - Describes a permission accepted by the user upon installing the - plugin. - type: "object" - properties: - Name: - type: "string" - Description: - type: "string" - Value: - type: "array" - items: - type: "string" - example: - - Name: "network" - Description: "" - Value: - - "host" - - Name: "mount" - Description: "" - Value: - - "/data" - - Name: "device" - Description: "" - Value: - - "/dev/cpu_dma_latency" - tags: ["Plugin"] - /plugins/{name}/json: - get: - summary: "Inspect a plugin" - operationId: "PluginInspect" - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/Plugin" - 404: - description: "plugin is not installed" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - tags: ["Plugin"] - /plugins/{name}: - delete: - summary: "Remove a plugin" - operationId: "PluginDelete" - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/Plugin" - 404: - description: "plugin is not installed" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - - name: "force" - in: "query" - description: | - Disable the plugin before removing. This may result in issues if the - plugin is in use by a container. - type: "boolean" - default: false - tags: ["Plugin"] - /plugins/{name}/enable: - post: - summary: "Enable a plugin" - operationId: "PluginEnable" - responses: - 200: - description: "no error" - 404: - description: "plugin is not installed" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - - name: "timeout" - in: "query" - description: "Set the HTTP client timeout (in seconds)" - type: "integer" - default: 0 - tags: ["Plugin"] - /plugins/{name}/disable: - post: - summary: "Disable a plugin" - operationId: "PluginDisable" - responses: - 200: - description: "no error" - 404: - description: "plugin is not installed" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - tags: ["Plugin"] - /plugins/{name}/upgrade: - post: - summary: "Upgrade a plugin" - operationId: "PluginUpgrade" - responses: - 204: - description: "no error" - 404: - description: "plugin not installed" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - - name: "remote" - in: "query" - description: | - Remote reference to upgrade to. - - The `:latest` tag is optional, and is used as the default if omitted. - required: true - type: "string" - - name: "X-Registry-Auth" - in: "header" - description: | - A base64url-encoded auth configuration to use when pulling a plugin - from a registry. - - Refer to the [authentication section](#section/Authentication) for - details. - type: "string" - - name: "body" - in: "body" - schema: - type: "array" - items: - description: | - Describes a permission accepted by the user upon installing the - plugin. - type: "object" - properties: - Name: - type: "string" - Description: - type: "string" - Value: - type: "array" - items: - type: "string" - example: - - Name: "network" - Description: "" - Value: - - "host" - - Name: "mount" - Description: "" - Value: - - "/data" - - Name: "device" - Description: "" - Value: - - "/dev/cpu_dma_latency" - tags: ["Plugin"] - /plugins/create: - post: - summary: "Create a plugin" - operationId: "PluginCreate" - consumes: - - "application/x-tar" - responses: - 204: - description: "no error" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "query" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - - name: "tarContext" - in: "body" - description: "Path to tar containing plugin rootfs and manifest" - schema: - type: "string" - format: "binary" - tags: ["Plugin"] - /plugins/{name}/push: - post: - summary: "Push a plugin" - operationId: "PluginPush" - description: | - Push a plugin to the registry. - parameters: - - name: "name" - in: "path" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - responses: - 200: - description: "no error" - 404: - description: "plugin not installed" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Plugin"] - /plugins/{name}/set: - post: - summary: "Configure a plugin" - operationId: "PluginSet" - consumes: - - "application/json" - parameters: - - name: "name" - in: "path" - description: | - The name of the plugin. The `:latest` tag is optional, and is the - default if omitted. - required: true - type: "string" - - name: "body" - in: "body" - schema: - type: "array" - items: - type: "string" - example: ["DEBUG=1"] - responses: - 204: - description: "No error" - 404: - description: "Plugin not installed" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Plugin"] - /nodes: - get: - summary: "List nodes" - operationId: "NodeList" - responses: - 200: - description: "no error" - schema: - type: "array" - items: - $ref: "#/definitions/Node" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "filters" - in: "query" - description: | - Filters to process on the nodes list, encoded as JSON (a `map[string][]string`). - - Available filters: - - `id=` - - `label=` - - `membership=`(`accepted`|`pending`)` - - `name=` - - `node.label=` - - `role=`(`manager`|`worker`)` - type: "string" - tags: ["Node"] - /nodes/{id}: - get: - summary: "Inspect a node" - operationId: "NodeInspect" - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/Node" - 404: - description: "no such node" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "The ID or name of the node" - type: "string" - required: true - tags: ["Node"] - delete: - summary: "Delete a node" - operationId: "NodeDelete" - responses: - 200: - description: "no error" - 404: - description: "no such node" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "The ID or name of the node" - type: "string" - required: true - - name: "force" - in: "query" - description: "Force remove a node from the swarm" - default: false - type: "boolean" - tags: ["Node"] - /nodes/{id}/update: - post: - summary: "Update a node" - operationId: "NodeUpdate" - responses: - 200: - description: "no error" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such node" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "The ID of the node" - type: "string" - required: true - - name: "body" - in: "body" - schema: - $ref: "#/definitions/NodeSpec" - - name: "version" - in: "query" - description: | - The version number of the node object being updated. This is required - to avoid conflicting writes. - type: "integer" - format: "int64" - required: true - tags: ["Node"] - /swarm: - get: - summary: "Inspect swarm" - operationId: "SwarmInspect" - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/Swarm" - 404: - description: "no such swarm" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Swarm"] - /swarm/init: - post: - summary: "Initialize a new swarm" - operationId: "SwarmInit" - produces: - - "application/json" - - "text/plain" - responses: - 200: - description: "no error" - schema: - description: "The node ID" - type: "string" - example: "7v2t30z9blmxuhnyo6s4cpenp" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is already part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "body" - in: "body" - required: true - schema: - type: "object" - properties: - ListenAddr: - description: | - Listen address used for inter-manager communication, as well - as determining the networking interface used for the VXLAN - Tunnel Endpoint (VTEP). This can either be an address/port - combination in the form `192.168.1.1:4567`, or an interface - followed by a port number, like `eth0:4567`. If the port number - is omitted, the default swarm listening port is used. - type: "string" - AdvertiseAddr: - description: | - Externally reachable address advertised to other nodes. This - can either be an address/port combination in the form - `192.168.1.1:4567`, or an interface followed by a port number, - like `eth0:4567`. If the port number is omitted, the port - number from the listen address is used. If `AdvertiseAddr` is - not specified, it will be automatically detected when possible. - type: "string" - DataPathAddr: - description: | - Address or interface to use for data path traffic (format: - ``), for example, `192.168.1.1`, or an interface, - like `eth0`. If `DataPathAddr` is unspecified, the same address - as `AdvertiseAddr` is used. - - The `DataPathAddr` specifies the address that global scope - network drivers will publish towards other nodes in order to - reach the containers running on this node. Using this parameter - it is possible to separate the container data traffic from the - management traffic of the cluster. - type: "string" - DataPathPort: - description: | - DataPathPort specifies the data path port number for data traffic. - Acceptable port range is 1024 to 49151. - if no port is set or is set to 0, default port 4789 will be used. - type: "integer" - format: "uint32" - DefaultAddrPool: - description: | - Default Address Pool specifies default subnet pools for global - scope networks. - type: "array" - items: - type: "string" - example: ["10.10.0.0/16", "20.20.0.0/16"] - ForceNewCluster: - description: "Force creation of a new swarm." - type: "boolean" - SubnetSize: - description: | - SubnetSize specifies the subnet size of the networks created - from the default subnet pool. - type: "integer" - format: "uint32" - Spec: - $ref: "#/definitions/SwarmSpec" - example: - ListenAddr: "0.0.0.0:2377" - AdvertiseAddr: "192.168.1.1:2377" - DataPathPort: 4789 - DefaultAddrPool: ["10.10.0.0/8", "20.20.0.0/8"] - SubnetSize: 24 - ForceNewCluster: false - Spec: - Orchestration: {} - Raft: {} - Dispatcher: {} - CAConfig: {} - EncryptionConfig: - AutoLockManagers: false - tags: ["Swarm"] - /swarm/join: - post: - summary: "Join an existing swarm" - operationId: "SwarmJoin" - responses: - 200: - description: "no error" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is already part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "body" - in: "body" - required: true - schema: - type: "object" - properties: - ListenAddr: - description: | - Listen address used for inter-manager communication if the node - gets promoted to manager, as well as determining the networking - interface used for the VXLAN Tunnel Endpoint (VTEP). - type: "string" - AdvertiseAddr: - description: | - Externally reachable address advertised to other nodes. This - can either be an address/port combination in the form - `192.168.1.1:4567`, or an interface followed by a port number, - like `eth0:4567`. If the port number is omitted, the port - number from the listen address is used. If `AdvertiseAddr` is - not specified, it will be automatically detected when possible. - type: "string" - DataPathAddr: - description: | - Address or interface to use for data path traffic (format: - ``), for example, `192.168.1.1`, or an interface, - like `eth0`. If `DataPathAddr` is unspecified, the same addres - as `AdvertiseAddr` is used. - - The `DataPathAddr` specifies the address that global scope - network drivers will publish towards other nodes in order to - reach the containers running on this node. Using this parameter - it is possible to separate the container data traffic from the - management traffic of the cluster. - - type: "string" - RemoteAddrs: - description: | - Addresses of manager nodes already participating in the swarm. - type: "array" - items: - type: "string" - JoinToken: - description: "Secret token for joining this swarm." - type: "string" - example: - ListenAddr: "0.0.0.0:2377" - AdvertiseAddr: "192.168.1.1:2377" - RemoteAddrs: - - "node1:2377" - JoinToken: "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2" - tags: ["Swarm"] - /swarm/leave: - post: - summary: "Leave a swarm" - operationId: "SwarmLeave" - responses: - 200: - description: "no error" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "force" - description: | - Force leave swarm, even if this is the last manager or that it will - break the cluster. - in: "query" - type: "boolean" - default: false - tags: ["Swarm"] - /swarm/update: - post: - summary: "Update a swarm" - operationId: "SwarmUpdate" - responses: - 200: - description: "no error" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "body" - in: "body" - required: true - schema: - $ref: "#/definitions/SwarmSpec" - - name: "version" - in: "query" - description: | - The version number of the swarm object being updated. This is - required to avoid conflicting writes. - type: "integer" - format: "int64" - required: true - - name: "rotateWorkerToken" - in: "query" - description: "Rotate the worker join token." - type: "boolean" - default: false - - name: "rotateManagerToken" - in: "query" - description: "Rotate the manager join token." - type: "boolean" - default: false - - name: "rotateManagerUnlockKey" - in: "query" - description: "Rotate the manager unlock key." - type: "boolean" - default: false - tags: ["Swarm"] - /swarm/unlockkey: - get: - summary: "Get the unlock key" - operationId: "SwarmUnlockkey" - consumes: - - "application/json" - responses: - 200: - description: "no error" - schema: - type: "object" - title: "UnlockKeyResponse" - properties: - UnlockKey: - description: "The swarm's unlock key." - type: "string" - example: - UnlockKey: "SWMKEY-1-7c37Cc8654o6p38HnroywCi19pllOnGtbdZEgtKxZu8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Swarm"] - /swarm/unlock: - post: - summary: "Unlock a locked manager" - operationId: "SwarmUnlock" - consumes: - - "application/json" - produces: - - "application/json" - parameters: - - name: "body" - in: "body" - required: true - schema: - type: "object" - properties: - UnlockKey: - description: "The swarm's unlock key." - type: "string" - example: - UnlockKey: "SWMKEY-1-7c37Cc8654o6p38HnroywCi19pllOnGtbdZEgtKxZu8" - responses: - 200: - description: "no error" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Swarm"] - /services: - get: - summary: "List services" - operationId: "ServiceList" - responses: - 200: - description: "no error" - schema: - type: "array" - items: - $ref: "#/definitions/Service" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "filters" - in: "query" - type: "string" - description: | - A JSON encoded value of the filters (a `map[string][]string`) to - process on the services list. - - Available filters: - - - `id=` - - `label=` - - `mode=["replicated"|"global"]` - - `name=` - - name: "status" - in: "query" - type: "boolean" - description: | - Include service status, with count of running and desired tasks. - tags: ["Service"] - /services/create: - post: - summary: "Create a service" - operationId: "ServiceCreate" - consumes: - - "application/json" - produces: - - "application/json" - responses: - 201: - description: "no error" - schema: - type: "object" - title: "ServiceCreateResponse" - properties: - ID: - description: "The ID of the created service." - type: "string" - Warning: - description: "Optional warning message" - type: "string" - example: - ID: "ak7w3gjqoa3kuz8xcpnyy0pvl" - Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 403: - description: "network is not eligible for services" - schema: - $ref: "#/definitions/ErrorResponse" - 409: - description: "name conflicts with an existing service" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "body" - in: "body" - required: true - schema: - allOf: - - $ref: "#/definitions/ServiceSpec" - - type: "object" - example: - Name: "web" - TaskTemplate: - ContainerSpec: - Image: "nginx:alpine" - Mounts: - - - ReadOnly: true - Source: "web-data" - Target: "/usr/share/nginx/html" - Type: "volume" - VolumeOptions: - DriverConfig: {} - Labels: - com.example.something: "something-value" - Hosts: ["10.10.10.10 host1", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 host2"] - User: "33" - DNSConfig: - Nameservers: ["8.8.8.8"] - Search: ["example.org"] - Options: ["timeout:3"] - Secrets: - - - File: - Name: "www.example.org.key" - UID: "33" - GID: "33" - Mode: 384 - SecretID: "fpjqlhnwb19zds35k8wn80lq9" - SecretName: "example_org_domain_key" - LogDriver: - Name: "json-file" - Options: - max-file: "3" - max-size: "10M" - Placement: {} - Resources: - Limits: - MemoryBytes: 104857600 - Reservations: {} - RestartPolicy: - Condition: "on-failure" - Delay: 10000000000 - MaxAttempts: 10 - Mode: - Replicated: - Replicas: 4 - UpdateConfig: - Parallelism: 2 - Delay: 1000000000 - FailureAction: "pause" - Monitor: 15000000000 - MaxFailureRatio: 0.15 - RollbackConfig: - Parallelism: 1 - Delay: 1000000000 - FailureAction: "pause" - Monitor: 15000000000 - MaxFailureRatio: 0.15 - EndpointSpec: - Ports: - - - Protocol: "tcp" - PublishedPort: 8080 - TargetPort: 80 - Labels: - foo: "bar" - - name: "X-Registry-Auth" - in: "header" - description: | - A base64url-encoded auth configuration for pulling from private - registries. - - Refer to the [authentication section](#section/Authentication) for - details. - type: "string" - tags: ["Service"] - /services/{id}: - get: - summary: "Inspect a service" - operationId: "ServiceInspect" - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/Service" - 404: - description: "no such service" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "ID or name of service." - required: true - type: "string" - - name: "insertDefaults" - in: "query" - description: "Fill empty fields with default values." - type: "boolean" - default: false - tags: ["Service"] - delete: - summary: "Delete a service" - operationId: "ServiceDelete" - responses: - 200: - description: "no error" - 404: - description: "no such service" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "ID or name of service." - required: true - type: "string" - tags: ["Service"] - /services/{id}/update: - post: - summary: "Update a service" - operationId: "ServiceUpdate" - consumes: ["application/json"] - produces: ["application/json"] - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/ServiceUpdateResponse" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such service" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "ID or name of service." - required: true - type: "string" - - name: "body" - in: "body" - required: true - schema: - allOf: - - $ref: "#/definitions/ServiceSpec" - - type: "object" - example: - Name: "top" - TaskTemplate: - ContainerSpec: - Image: "busybox" - Args: - - "top" - Resources: - Limits: {} - Reservations: {} - RestartPolicy: - Condition: "any" - MaxAttempts: 0 - Placement: {} - ForceUpdate: 0 - Mode: - Replicated: - Replicas: 1 - UpdateConfig: - Parallelism: 2 - Delay: 1000000000 - FailureAction: "pause" - Monitor: 15000000000 - MaxFailureRatio: 0.15 - RollbackConfig: - Parallelism: 1 - Delay: 1000000000 - FailureAction: "pause" - Monitor: 15000000000 - MaxFailureRatio: 0.15 - EndpointSpec: - Mode: "vip" - - - name: "version" - in: "query" - description: | - The version number of the service object being updated. This is - required to avoid conflicting writes. - This version number should be the value as currently set on the - service *before* the update. You can find the current version by - calling `GET /services/{id}` - required: true - type: "integer" - - name: "registryAuthFrom" - in: "query" - description: | - If the `X-Registry-Auth` header is not specified, this parameter - indicates where to find registry authorization credentials. - type: "string" - enum: ["spec", "previous-spec"] - default: "spec" - - name: "rollback" - in: "query" - description: | - Set to this parameter to `previous` to cause a server-side rollback - to the previous service spec. The supplied spec will be ignored in - this case. - type: "string" - - name: "X-Registry-Auth" - in: "header" - description: | - A base64url-encoded auth configuration for pulling from private - registries. - - Refer to the [authentication section](#section/Authentication) for - details. - type: "string" - - tags: ["Service"] - /services/{id}/logs: - get: - summary: "Get service logs" - description: | - Get `stdout` and `stderr` logs from a service. See also - [`/containers/{id}/logs`](#operation/ContainerLogs). - - **Note**: This endpoint works only for services with the `local`, - `json-file` or `journald` logging drivers. - operationId: "ServiceLogs" - responses: - 200: - description: "logs returned as a stream in response body" - schema: - type: "string" - format: "binary" - 404: - description: "no such service" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such service: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID or name of the service" - type: "string" - - name: "details" - in: "query" - description: "Show service context and extra details provided to logs." - type: "boolean" - default: false - - name: "follow" - in: "query" - description: "Keep connection after returning logs." - type: "boolean" - default: false - - name: "stdout" - in: "query" - description: "Return logs from `stdout`" - type: "boolean" - default: false - - name: "stderr" - in: "query" - description: "Return logs from `stderr`" - type: "boolean" - default: false - - name: "since" - in: "query" - description: "Only return logs since this time, as a UNIX timestamp" - type: "integer" - default: 0 - - name: "timestamps" - in: "query" - description: "Add timestamps to every log line" - type: "boolean" - default: false - - name: "tail" - in: "query" - description: | - Only return this number of log lines from the end of the logs. - Specify as an integer or `all` to output all log lines. - type: "string" - default: "all" - tags: ["Service"] - /tasks: - get: - summary: "List tasks" - operationId: "TaskList" - produces: - - "application/json" - responses: - 200: - description: "no error" - schema: - type: "array" - items: - $ref: "#/definitions/Task" - example: - - ID: "0kzzo1i0y4jz6027t0k7aezc7" - Version: - Index: 71 - CreatedAt: "2016-06-07T21:07:31.171892745Z" - UpdatedAt: "2016-06-07T21:07:31.376370513Z" - Spec: - ContainerSpec: - Image: "redis" - Resources: - Limits: {} - Reservations: {} - RestartPolicy: - Condition: "any" - MaxAttempts: 0 - Placement: {} - ServiceID: "9mnpnzenvg8p8tdbtq4wvbkcz" - Slot: 1 - NodeID: "60gvrl6tm78dmak4yl7srz94v" - Status: - Timestamp: "2016-06-07T21:07:31.290032978Z" - State: "running" - Message: "started" - ContainerStatus: - ContainerID: "e5d62702a1b48d01c3e02ca1e0212a250801fa8d67caca0b6f35919ebc12f035" - PID: 677 - DesiredState: "running" - NetworksAttachments: - - Network: - ID: "4qvuz4ko70xaltuqbt8956gd1" - Version: - Index: 18 - CreatedAt: "2016-06-07T20:31:11.912919752Z" - UpdatedAt: "2016-06-07T21:07:29.955277358Z" - Spec: - Name: "ingress" - Labels: - com.docker.swarm.internal: "true" - DriverConfiguration: {} - IPAMOptions: - Driver: {} - Configs: - - Subnet: "10.255.0.0/16" - Gateway: "10.255.0.1" - DriverState: - Name: "overlay" - Options: - com.docker.network.driver.overlay.vxlanid_list: "256" - IPAMOptions: - Driver: - Name: "default" - Configs: - - Subnet: "10.255.0.0/16" - Gateway: "10.255.0.1" - Addresses: - - "10.255.0.10/16" - - ID: "1yljwbmlr8er2waf8orvqpwms" - Version: - Index: 30 - CreatedAt: "2016-06-07T21:07:30.019104782Z" - UpdatedAt: "2016-06-07T21:07:30.231958098Z" - Name: "hopeful_cori" - Spec: - ContainerSpec: - Image: "redis" - Resources: - Limits: {} - Reservations: {} - RestartPolicy: - Condition: "any" - MaxAttempts: 0 - Placement: {} - ServiceID: "9mnpnzenvg8p8tdbtq4wvbkcz" - Slot: 1 - NodeID: "60gvrl6tm78dmak4yl7srz94v" - Status: - Timestamp: "2016-06-07T21:07:30.202183143Z" - State: "shutdown" - Message: "shutdown" - ContainerStatus: - ContainerID: "1cf8d63d18e79668b0004a4be4c6ee58cddfad2dae29506d8781581d0688a213" - DesiredState: "shutdown" - NetworksAttachments: - - Network: - ID: "4qvuz4ko70xaltuqbt8956gd1" - Version: - Index: 18 - CreatedAt: "2016-06-07T20:31:11.912919752Z" - UpdatedAt: "2016-06-07T21:07:29.955277358Z" - Spec: - Name: "ingress" - Labels: - com.docker.swarm.internal: "true" - DriverConfiguration: {} - IPAMOptions: - Driver: {} - Configs: - - Subnet: "10.255.0.0/16" - Gateway: "10.255.0.1" - DriverState: - Name: "overlay" - Options: - com.docker.network.driver.overlay.vxlanid_list: "256" - IPAMOptions: - Driver: - Name: "default" - Configs: - - Subnet: "10.255.0.0/16" - Gateway: "10.255.0.1" - Addresses: - - "10.255.0.5/16" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "filters" - in: "query" - type: "string" - description: | - A JSON encoded value of the filters (a `map[string][]string`) to - process on the tasks list. - - Available filters: - - - `desired-state=(running | shutdown | accepted)` - - `id=` - - `label=key` or `label="key=value"` - - `name=` - - `node=` - - `service=` - tags: ["Task"] - /tasks/{id}: - get: - summary: "Inspect a task" - operationId: "TaskInspect" - produces: - - "application/json" - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/Task" - 404: - description: "no such task" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "ID of the task" - required: true - type: "string" - tags: ["Task"] - /tasks/{id}/logs: - get: - summary: "Get task logs" - description: | - Get `stdout` and `stderr` logs from a task. - See also [`/containers/{id}/logs`](#operation/ContainerLogs). - - **Note**: This endpoint works only for services with the `local`, - `json-file` or `journald` logging drivers. - operationId: "TaskLogs" - responses: - 200: - description: "logs returned as a stream in response body" - schema: - type: "string" - format: "binary" - 404: - description: "no such task" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such task: c2ada9df5af8" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - description: "ID of the task" - type: "string" - - name: "details" - in: "query" - description: "Show task context and extra details provided to logs." - type: "boolean" - default: false - - name: "follow" - in: "query" - description: "Keep connection after returning logs." - type: "boolean" - default: false - - name: "stdout" - in: "query" - description: "Return logs from `stdout`" - type: "boolean" - default: false - - name: "stderr" - in: "query" - description: "Return logs from `stderr`" - type: "boolean" - default: false - - name: "since" - in: "query" - description: "Only return logs since this time, as a UNIX timestamp" - type: "integer" - default: 0 - - name: "timestamps" - in: "query" - description: "Add timestamps to every log line" - type: "boolean" - default: false - - name: "tail" - in: "query" - description: | - Only return this number of log lines from the end of the logs. - Specify as an integer or `all` to output all log lines. - type: "string" - default: "all" - tags: ["Task"] - /secrets: - get: - summary: "List secrets" - operationId: "SecretList" - produces: - - "application/json" - responses: - 200: - description: "no error" - schema: - type: "array" - items: - $ref: "#/definitions/Secret" - example: - - ID: "blt1owaxmitz71s9v5zh81zun" - Version: - Index: 85 - CreatedAt: "2017-07-20T13:55:28.678958722Z" - UpdatedAt: "2017-07-20T13:55:28.678958722Z" - Spec: - Name: "mysql-passwd" - Labels: - some.label: "some.value" - Driver: - Name: "secret-bucket" - Options: - OptionA: "value for driver option A" - OptionB: "value for driver option B" - - ID: "ktnbjxoalbkvbvedmg1urrz8h" - Version: - Index: 11 - CreatedAt: "2016-11-05T01:20:17.327670065Z" - UpdatedAt: "2016-11-05T01:20:17.327670065Z" - Spec: - Name: "app-dev.crt" - Labels: - foo: "bar" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "filters" - in: "query" - type: "string" - description: | - A JSON encoded value of the filters (a `map[string][]string`) to - process on the secrets list. - - Available filters: - - - `id=` - - `label= or label==value` - - `name=` - - `names=` - tags: ["Secret"] - /secrets/create: - post: - summary: "Create a secret" - operationId: "SecretCreate" - consumes: - - "application/json" - produces: - - "application/json" - responses: - 201: - description: "no error" - schema: - $ref: "#/definitions/IdResponse" - 409: - description: "name conflicts with an existing object" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "body" - in: "body" - schema: - allOf: - - $ref: "#/definitions/SecretSpec" - - type: "object" - example: - Name: "app-key.crt" - Labels: - foo: "bar" - Data: "VEhJUyBJUyBOT1QgQSBSRUFMIENFUlRJRklDQVRFCg==" - Driver: - Name: "secret-bucket" - Options: - OptionA: "value for driver option A" - OptionB: "value for driver option B" - tags: ["Secret"] - /secrets/{id}: - get: - summary: "Inspect a secret" - operationId: "SecretInspect" - produces: - - "application/json" - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/Secret" - examples: - application/json: - ID: "ktnbjxoalbkvbvedmg1urrz8h" - Version: - Index: 11 - CreatedAt: "2016-11-05T01:20:17.327670065Z" - UpdatedAt: "2016-11-05T01:20:17.327670065Z" - Spec: - Name: "app-dev.crt" - Labels: - foo: "bar" - Driver: - Name: "secret-bucket" - Options: - OptionA: "value for driver option A" - OptionB: "value for driver option B" - - 404: - description: "secret not found" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - type: "string" - description: "ID of the secret" - tags: ["Secret"] - delete: - summary: "Delete a secret" - operationId: "SecretDelete" - produces: - - "application/json" - responses: - 204: - description: "no error" - 404: - description: "secret not found" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - type: "string" - description: "ID of the secret" - tags: ["Secret"] - /secrets/{id}/update: - post: - summary: "Update a Secret" - operationId: "SecretUpdate" - responses: - 200: - description: "no error" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such secret" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "The ID or name of the secret" - type: "string" - required: true - - name: "body" - in: "body" - schema: - $ref: "#/definitions/SecretSpec" - description: | - The spec of the secret to update. Currently, only the Labels field - can be updated. All other fields must remain unchanged from the - [SecretInspect endpoint](#operation/SecretInspect) response values. - - name: "version" - in: "query" - description: | - The version number of the secret object being updated. This is - required to avoid conflicting writes. - type: "integer" - format: "int64" - required: true - tags: ["Secret"] - /configs: - get: - summary: "List configs" - operationId: "ConfigList" - produces: - - "application/json" - responses: - 200: - description: "no error" - schema: - type: "array" - items: - $ref: "#/definitions/Config" - example: - - ID: "ktnbjxoalbkvbvedmg1urrz8h" - Version: - Index: 11 - CreatedAt: "2016-11-05T01:20:17.327670065Z" - UpdatedAt: "2016-11-05T01:20:17.327670065Z" - Spec: - Name: "server.conf" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "filters" - in: "query" - type: "string" - description: | - A JSON encoded value of the filters (a `map[string][]string`) to - process on the configs list. - - Available filters: - - - `id=` - - `label= or label==value` - - `name=` - - `names=` - tags: ["Config"] - /configs/create: - post: - summary: "Create a config" - operationId: "ConfigCreate" - consumes: - - "application/json" - produces: - - "application/json" - responses: - 201: - description: "no error" - schema: - $ref: "#/definitions/IdResponse" - 409: - description: "name conflicts with an existing object" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "body" - in: "body" - schema: - allOf: - - $ref: "#/definitions/ConfigSpec" - - type: "object" - example: - Name: "server.conf" - Labels: - foo: "bar" - Data: "VEhJUyBJUyBOT1QgQSBSRUFMIENFUlRJRklDQVRFCg==" - tags: ["Config"] - /configs/{id}: - get: - summary: "Inspect a config" - operationId: "ConfigInspect" - produces: - - "application/json" - responses: - 200: - description: "no error" - schema: - $ref: "#/definitions/Config" - examples: - application/json: - ID: "ktnbjxoalbkvbvedmg1urrz8h" - Version: - Index: 11 - CreatedAt: "2016-11-05T01:20:17.327670065Z" - UpdatedAt: "2016-11-05T01:20:17.327670065Z" - Spec: - Name: "app-dev.crt" - 404: - description: "config not found" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - type: "string" - description: "ID of the config" - tags: ["Config"] - delete: - summary: "Delete a config" - operationId: "ConfigDelete" - produces: - - "application/json" - responses: - 204: - description: "no error" - 404: - description: "config not found" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - required: true - type: "string" - description: "ID of the config" - tags: ["Config"] - /configs/{id}/update: - post: - summary: "Update a Config" - operationId: "ConfigUpdate" - responses: - 200: - description: "no error" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 404: - description: "no such config" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - 503: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "id" - in: "path" - description: "The ID or name of the config" - type: "string" - required: true - - name: "body" - in: "body" - schema: - $ref: "#/definitions/ConfigSpec" - description: | - The spec of the config to update. Currently, only the Labels field - can be updated. All other fields must remain unchanged from the - [ConfigInspect endpoint](#operation/ConfigInspect) response values. - - name: "version" - in: "query" - description: | - The version number of the config object being updated. This is - required to avoid conflicting writes. - type: "integer" - format: "int64" - required: true - tags: ["Config"] - /distribution/{name}/json: - get: - summary: "Get image information from the registry" - description: | - Return image digest and platform information by contacting the registry. - operationId: "DistributionInspect" - produces: - - "application/json" - responses: - 200: - description: "descriptor and platform information" - schema: - type: "object" - x-go-name: DistributionInspect - title: "DistributionInspectResponse" - required: [Descriptor, Platforms] - properties: - Descriptor: - type: "object" - description: | - A descriptor struct containing digest, media type, and size. - properties: - MediaType: - type: "string" - Size: - type: "integer" - format: "int64" - Digest: - type: "string" - URLs: - type: "array" - items: - type: "string" - Platforms: - type: "array" - description: | - An array containing all platforms supported by the image. - items: - type: "object" - properties: - Architecture: - type: "string" - OS: - type: "string" - OSVersion: - type: "string" - OSFeatures: - type: "array" - items: - type: "string" - Variant: - type: "string" - Features: - type: "array" - items: - type: "string" - examples: - application/json: - Descriptor: - MediaType: "application/vnd.docker.distribution.manifest.v2+json" - Digest: "sha256:c0537ff6a5218ef531ece93d4984efc99bbf3f7497c0a7726c88e2bb7584dc96" - Size: 3987495 - URLs: - - "" - Platforms: - - Architecture: "amd64" - OS: "linux" - OSVersion: "" - OSFeatures: - - "" - Variant: "" - Features: - - "" - 401: - description: "Failed authentication or no image found" - schema: - $ref: "#/definitions/ErrorResponse" - examples: - application/json: - message: "No such image: someimage (tag: latest)" - 500: - description: "Server error" - schema: - $ref: "#/definitions/ErrorResponse" - parameters: - - name: "name" - in: "path" - description: "Image name or id" - type: "string" - required: true - tags: ["Distribution"] - /session: - post: - summary: "Initialize interactive session" - description: | - Start a new interactive session with a server. Session allows server to - call back to the client for advanced capabilities. - - ### Hijacking - - This endpoint hijacks the HTTP connection to HTTP2 transport that allows - the client to expose gPRC services on that connection. - - For example, the client sends this request to upgrade the connection: - - ``` - POST /session HTTP/1.1 - Upgrade: h2c - Connection: Upgrade - ``` - - The Docker daemon responds with a `101 UPGRADED` response follow with - the raw stream: - - ``` - HTTP/1.1 101 UPGRADED - Connection: Upgrade - Upgrade: h2c - ``` - operationId: "Session" - produces: - - "application/vnd.docker.raw-stream" - responses: - 101: - description: "no error, hijacking successful" - 400: - description: "bad parameter" - schema: - $ref: "#/definitions/ErrorResponse" - 500: - description: "server error" - schema: - $ref: "#/definitions/ErrorResponse" - tags: ["Session"] diff --git a/vendor/github.com/docker/docker/api/types/auth.go b/vendor/github.com/docker/docker/api/types/auth.go deleted file mode 100644 index ddf15bb182d..00000000000 --- a/vendor/github.com/docker/docker/api/types/auth.go +++ /dev/null @@ -1,22 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -// AuthConfig contains authorization information for connecting to a Registry -type AuthConfig struct { - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - Auth string `json:"auth,omitempty"` - - // Email is an optional value associated with the username. - // This field is deprecated and will be removed in a later - // version of docker. - Email string `json:"email,omitempty"` - - ServerAddress string `json:"serveraddress,omitempty"` - - // IdentityToken is used to authenticate the user and get - // an access token for the registry. - IdentityToken string `json:"identitytoken,omitempty"` - - // RegistryToken is a bearer token to be sent to a registry - RegistryToken string `json:"registrytoken,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/blkiodev/blkio.go b/vendor/github.com/docker/docker/api/types/blkiodev/blkio.go deleted file mode 100644 index bf3463b90e7..00000000000 --- a/vendor/github.com/docker/docker/api/types/blkiodev/blkio.go +++ /dev/null @@ -1,23 +0,0 @@ -package blkiodev // import "github.com/docker/docker/api/types/blkiodev" - -import "fmt" - -// WeightDevice is a structure that holds device:weight pair -type WeightDevice struct { - Path string - Weight uint16 -} - -func (w *WeightDevice) String() string { - return fmt.Sprintf("%s:%d", w.Path, w.Weight) -} - -// ThrottleDevice is a structure that holds device:rate_per_second pair -type ThrottleDevice struct { - Path string - Rate uint64 -} - -func (t *ThrottleDevice) String() string { - return fmt.Sprintf("%s:%d", t.Path, t.Rate) -} diff --git a/vendor/github.com/docker/docker/api/types/client.go b/vendor/github.com/docker/docker/api/types/client.go deleted file mode 100644 index 9c464b73e25..00000000000 --- a/vendor/github.com/docker/docker/api/types/client.go +++ /dev/null @@ -1,419 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -import ( - "bufio" - "io" - "net" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - units "github.com/docker/go-units" -) - -// CheckpointCreateOptions holds parameters to create a checkpoint from a container -type CheckpointCreateOptions struct { - CheckpointID string - CheckpointDir string - Exit bool -} - -// CheckpointListOptions holds parameters to list checkpoints for a container -type CheckpointListOptions struct { - CheckpointDir string -} - -// CheckpointDeleteOptions holds parameters to delete a checkpoint from a container -type CheckpointDeleteOptions struct { - CheckpointID string - CheckpointDir string -} - -// ContainerAttachOptions holds parameters to attach to a container. -type ContainerAttachOptions struct { - Stream bool - Stdin bool - Stdout bool - Stderr bool - DetachKeys string - Logs bool -} - -// ContainerCommitOptions holds parameters to commit changes into a container. -type ContainerCommitOptions struct { - Reference string - Comment string - Author string - Changes []string - Pause bool - Config *container.Config -} - -// ContainerExecInspect holds information returned by exec inspect. -type ContainerExecInspect struct { - ExecID string `json:"ID"` - ContainerID string - Running bool - ExitCode int - Pid int -} - -// ContainerListOptions holds parameters to list containers with. -type ContainerListOptions struct { - Quiet bool - Size bool - All bool - Latest bool - Since string - Before string - Limit int - Filters filters.Args -} - -// ContainerLogsOptions holds parameters to filter logs with. -type ContainerLogsOptions struct { - ShowStdout bool - ShowStderr bool - Since string - Until string - Timestamps bool - Follow bool - Tail string - Details bool -} - -// ContainerRemoveOptions holds parameters to remove containers. -type ContainerRemoveOptions struct { - RemoveVolumes bool - RemoveLinks bool - Force bool -} - -// ContainerStartOptions holds parameters to start containers. -type ContainerStartOptions struct { - CheckpointID string - CheckpointDir string -} - -// CopyToContainerOptions holds information -// about files to copy into a container -type CopyToContainerOptions struct { - AllowOverwriteDirWithFile bool - CopyUIDGID bool -} - -// EventsOptions holds parameters to filter events with. -type EventsOptions struct { - Since string - Until string - Filters filters.Args -} - -// NetworkListOptions holds parameters to filter the list of networks with. -type NetworkListOptions struct { - Filters filters.Args -} - -// HijackedResponse holds connection information for a hijacked request. -type HijackedResponse struct { - Conn net.Conn - Reader *bufio.Reader -} - -// Close closes the hijacked connection and reader. -func (h *HijackedResponse) Close() { - h.Conn.Close() -} - -// CloseWriter is an interface that implements structs -// that close input streams to prevent from writing. -type CloseWriter interface { - CloseWrite() error -} - -// CloseWrite closes a readWriter for writing. -func (h *HijackedResponse) CloseWrite() error { - if conn, ok := h.Conn.(CloseWriter); ok { - return conn.CloseWrite() - } - return nil -} - -// ImageBuildOptions holds the information -// necessary to build images. -type ImageBuildOptions struct { - Tags []string - SuppressOutput bool - RemoteContext string - NoCache bool - Remove bool - ForceRemove bool - PullParent bool - Isolation container.Isolation - CPUSetCPUs string - CPUSetMems string - CPUShares int64 - CPUQuota int64 - CPUPeriod int64 - Memory int64 - MemorySwap int64 - CgroupParent string - NetworkMode string - ShmSize int64 - Dockerfile string - Ulimits []*units.Ulimit - // BuildArgs needs to be a *string instead of just a string so that - // we can tell the difference between "" (empty string) and no value - // at all (nil). See the parsing of buildArgs in - // api/server/router/build/build_routes.go for even more info. - BuildArgs map[string]*string - AuthConfigs map[string]AuthConfig - Context io.Reader - Labels map[string]string - // squash the resulting image's layers to the parent - // preserves the original image and creates a new one from the parent with all - // the changes applied to a single layer - Squash bool - // CacheFrom specifies images that are used for matching cache. Images - // specified here do not need to have a valid parent chain to match cache. - CacheFrom []string - SecurityOpt []string - ExtraHosts []string // List of extra hosts - Target string - SessionID string - Platform string - // Version specifies the version of the unerlying builder to use - Version BuilderVersion - // BuildID is an optional identifier that can be passed together with the - // build request. The same identifier can be used to gracefully cancel the - // build with the cancel request. - BuildID string - // Outputs defines configurations for exporting build results. Only supported - // in BuildKit mode - Outputs []ImageBuildOutput -} - -// ImageBuildOutput defines configuration for exporting a build result -type ImageBuildOutput struct { - Type string - Attrs map[string]string -} - -// BuilderVersion sets the version of underlying builder to use -type BuilderVersion string - -const ( - // BuilderV1 is the first generation builder in docker daemon - BuilderV1 BuilderVersion = "1" - // BuilderBuildKit is builder based on moby/buildkit project - BuilderBuildKit BuilderVersion = "2" -) - -// ImageBuildResponse holds information -// returned by a server after building -// an image. -type ImageBuildResponse struct { - Body io.ReadCloser - OSType string -} - -// ImageCreateOptions holds information to create images. -type ImageCreateOptions struct { - RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry. - Platform string // Platform is the target platform of the image if it needs to be pulled from the registry. -} - -// ImageImportSource holds source information for ImageImport -type ImageImportSource struct { - Source io.Reader // Source is the data to send to the server to create this image from. You must set SourceName to "-" to leverage this. - SourceName string // SourceName is the name of the image to pull. Set to "-" to leverage the Source attribute. -} - -// ImageImportOptions holds information to import images from the client host. -type ImageImportOptions struct { - Tag string // Tag is the name to tag this image with. This attribute is deprecated. - Message string // Message is the message to tag the image with - Changes []string // Changes are the raw changes to apply to this image - Platform string // Platform is the target platform of the image -} - -// ImageListOptions holds parameters to filter the list of images with. -type ImageListOptions struct { - All bool - Filters filters.Args -} - -// ImageLoadResponse returns information to the client about a load process. -type ImageLoadResponse struct { - // Body must be closed to avoid a resource leak - Body io.ReadCloser - JSON bool -} - -// ImagePullOptions holds information to pull images. -type ImagePullOptions struct { - All bool - RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry - PrivilegeFunc RequestPrivilegeFunc - Platform 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() (string, error) - -// ImagePushOptions holds information to push images. -type ImagePushOptions ImagePullOptions - -// ImageRemoveOptions holds parameters to remove images. -type ImageRemoveOptions struct { - Force bool - PruneChildren bool -} - -// ImageSearchOptions holds parameters to search images with. -type ImageSearchOptions struct { - RegistryAuth string - PrivilegeFunc RequestPrivilegeFunc - Filters filters.Args - Limit int -} - -// ResizeOptions holds parameters to resize a tty. -// It can be used to resize container ttys and -// exec process ttys too. -type ResizeOptions struct { - Height uint - Width uint -} - -// NodeListOptions holds parameters to list nodes with. -type NodeListOptions struct { - Filters filters.Args -} - -// NodeRemoveOptions holds parameters to remove nodes with. -type NodeRemoveOptions struct { - Force bool -} - -// ServiceCreateOptions contains the options to use when creating a service. -type ServiceCreateOptions struct { - // EncodedRegistryAuth is the encoded registry authorization credentials to - // use when updating the service. - // - // This field follows the format of the X-Registry-Auth header. - EncodedRegistryAuth string - - // QueryRegistry indicates whether the service update requires - // contacting a registry. A registry may be contacted to retrieve - // the image digest and manifest, which in turn can be used to update - // platform or other information about the service. - QueryRegistry bool -} - -// ServiceCreateResponse contains the information returned to a client -// on the creation of a new service. -type ServiceCreateResponse struct { - // ID is the ID of the created service. - ID string - // Warnings is a set of non-fatal warning messages to pass on to the user. - Warnings []string `json:",omitempty"` -} - -// Values for RegistryAuthFrom in ServiceUpdateOptions -const ( - RegistryAuthFromSpec = "spec" - RegistryAuthFromPreviousSpec = "previous-spec" -) - -// ServiceUpdateOptions contains the options to be used for updating services. -type ServiceUpdateOptions struct { - // EncodedRegistryAuth is the encoded registry authorization credentials to - // use when updating the service. - // - // This field follows the format of the X-Registry-Auth header. - EncodedRegistryAuth string - - // TODO(stevvooe): Consider moving the version parameter of ServiceUpdate - // into this field. While it does open API users up to racy writes, most - // users may not need that level of consistency in practice. - - // RegistryAuthFrom specifies where to find the registry authorization - // credentials if they are not given in EncodedRegistryAuth. Valid - // values are "spec" and "previous-spec". - RegistryAuthFrom string - - // Rollback indicates whether a server-side rollback should be - // performed. When this is set, the provided spec will be ignored. - // The valid values are "previous" and "none". An empty value is the - // same as "none". - Rollback string - - // QueryRegistry indicates whether the service update requires - // contacting a registry. A registry may be contacted to retrieve - // the image digest and manifest, which in turn can be used to update - // platform or other information about the service. - QueryRegistry bool -} - -// ServiceListOptions holds parameters to list services with. -type ServiceListOptions struct { - Filters filters.Args - - // Status indicates whether the server should include the service task - // count of running and desired tasks. - Status bool -} - -// ServiceInspectOptions holds parameters related to the "service inspect" -// operation. -type ServiceInspectOptions struct { - InsertDefaults bool -} - -// TaskListOptions holds parameters to list tasks with. -type TaskListOptions struct { - Filters filters.Args -} - -// PluginRemoveOptions holds parameters to remove plugins. -type PluginRemoveOptions struct { - Force bool -} - -// PluginEnableOptions holds parameters to enable plugins. -type PluginEnableOptions struct { - Timeout int -} - -// PluginDisableOptions holds parameters to disable plugins. -type PluginDisableOptions struct { - Force bool -} - -// 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 - AcceptPermissionsFunc func(PluginPrivileges) (bool, error) - Args []string -} - -// SwarmUnlockKeyResponse contains the response for Engine API: -// GET /swarm/unlockkey -type SwarmUnlockKeyResponse struct { - // UnlockKey is the unlock key in ASCII-armored format. - UnlockKey string -} - -// PluginCreateOptions hold all options to plugin create. -type PluginCreateOptions struct { - RepoName string -} diff --git a/vendor/github.com/docker/docker/api/types/configs.go b/vendor/github.com/docker/docker/api/types/configs.go deleted file mode 100644 index 3dd133a3a58..00000000000 --- a/vendor/github.com/docker/docker/api/types/configs.go +++ /dev/null @@ -1,66 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -import ( - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/network" - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - -// configs holds structs used for internal communication between the -// frontend (such as an http server) and the backend (such as the -// docker daemon). - -// ContainerCreateConfig is the parameter set to ContainerCreate() -type ContainerCreateConfig struct { - Name string - Config *container.Config - HostConfig *container.HostConfig - NetworkingConfig *network.NetworkingConfig - Platform *specs.Platform - AdjustCPUShares bool -} - -// ContainerRmConfig holds arguments for the container remove -// operation. This struct is used to tell the backend what operations -// to perform. -type ContainerRmConfig struct { - ForceRemove, RemoveVolume, RemoveLink bool -} - -// ExecConfig is a small subset of the Config struct that holds the configuration -// for the exec feature of docker. -type ExecConfig struct { - User string // User that will run the command - Privileged bool // Is the container in privileged mode - Tty bool // Attach standard streams to a tty. - AttachStdin bool // Attach the standard input, makes possible user interaction - AttachStderr bool // Attach the standard error - AttachStdout bool // Attach the standard output - Detach bool // Execute in detach mode - DetachKeys string // Escape keys for detach - Env []string // Environment variables - WorkingDir string // Working directory - Cmd []string // Execution commands and args -} - -// PluginRmConfig holds arguments for plugin remove. -type PluginRmConfig struct { - ForceRemove bool -} - -// PluginEnableConfig holds arguments for plugin enable -type PluginEnableConfig struct { - Timeout int -} - -// PluginDisableConfig holds arguments for plugin disable. -type PluginDisableConfig struct { - ForceDisable bool -} - -// NetworkListConfig stores the options available for listing networks -type NetworkListConfig struct { - // TODO(@cpuguy83): naming is hard, this is pulled from what was being used in the router before moving here - Detailed bool - Verbose bool -} diff --git a/vendor/github.com/docker/docker/api/types/container/config.go b/vendor/github.com/docker/docker/api/types/container/config.go deleted file mode 100644 index f767195b94b..00000000000 --- a/vendor/github.com/docker/docker/api/types/container/config.go +++ /dev/null @@ -1,69 +0,0 @@ -package container // import "github.com/docker/docker/api/types/container" - -import ( - "time" - - "github.com/docker/docker/api/types/strslice" - "github.com/docker/go-connections/nat" -) - -// MinimumDuration puts a minimum on user configured duration. -// This is to prevent API error on time unit. For example, API may -// set 3 as healthcheck interval with intention of 3 seconds, but -// Docker interprets it as 3 nanoseconds. -const MinimumDuration = 1 * time.Millisecond - -// HealthConfig holds configuration settings for the HEALTHCHECK feature. -type HealthConfig struct { - // Test is the test to perform to check that the container is healthy. - // An empty slice means to inherit the default. - // The options are: - // {} : inherit healthcheck - // {"NONE"} : disable healthcheck - // {"CMD", args...} : exec arguments directly - // {"CMD-SHELL", command} : run command with system's default shell - Test []string `json:",omitempty"` - - // Zero means to inherit. Durations are expressed as integer nanoseconds. - Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks. - Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung. - StartPeriod time.Duration `json:",omitempty"` // The start period for the container to initialize before the retries starts to count down. - - // Retries is the number of consecutive failures needed to consider a container as unhealthy. - // Zero means inherit. - Retries int `json:",omitempty"` -} - -// Config contains the configuration data about a container. -// It should hold only portable information about the container. -// Here, "portable" means "independent from the host we are running on". -// Non-portable information *should* appear in HostConfig. -// All fields added to this struct must be marked `omitempty` to keep getting -// predictable hashes from the old `v1Compatibility` configuration. -type Config struct { - Hostname string // Hostname - Domainname string // Domainname - User string // User that will run the command(s) inside the container, also support user:group - AttachStdin bool // Attach the standard input, makes possible user interaction - AttachStdout bool // Attach the standard output - AttachStderr bool // Attach the standard error - ExposedPorts nat.PortSet `json:",omitempty"` // List of exposed ports - Tty bool // Attach standard streams to a tty, including stdin if it is not closed. - OpenStdin bool // Open stdin - StdinOnce bool // If true, close stdin after the 1 attached client disconnects. - Env []string // List of environment variable to set in the container - Cmd strslice.StrSlice // Command to run when starting the container - Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy - ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (meaning treat as a command line) (Windows specific). - Image string // Name of the image as it was passed by the operator (e.g. could be symbolic) - Volumes map[string]struct{} // List of volumes (mounts) used for the container - WorkingDir string // Current directory (PWD) in the command will be launched - Entrypoint strslice.StrSlice // Entrypoint to run when starting the container - NetworkDisabled bool `json:",omitempty"` // Is network disabled - MacAddress string `json:",omitempty"` // Mac Address of the container - OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile - Labels map[string]string // List of labels set to this container - StopSignal string `json:",omitempty"` // Signal to stop a container - StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container - Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT -} diff --git a/vendor/github.com/docker/docker/api/types/container/container_changes.go b/vendor/github.com/docker/docker/api/types/container/container_changes.go deleted file mode 100644 index 16dd5019eef..00000000000 --- a/vendor/github.com/docker/docker/api/types/container/container_changes.go +++ /dev/null @@ -1,20 +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 -// ---------------------------------------------------------------------------- - -// ContainerChangeResponseItem change item in response to ContainerChanges operation -// swagger:model ContainerChangeResponseItem -type ContainerChangeResponseItem struct { - - // Kind of change - // Required: true - Kind uint8 `json:"Kind"` - - // Path to file that has changed - // Required: true - Path string `json:"Path"` -} diff --git a/vendor/github.com/docker/docker/api/types/container/container_create.go b/vendor/github.com/docker/docker/api/types/container/container_create.go deleted file mode 100644 index d0c852f84d5..00000000000 --- a/vendor/github.com/docker/docker/api/types/container/container_create.go +++ /dev/null @@ -1,20 +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 -// ---------------------------------------------------------------------------- - -// ContainerCreateCreatedBody OK response to ContainerCreate operation -// swagger:model ContainerCreateCreatedBody -type ContainerCreateCreatedBody struct { - - // The ID of the created container - // Required: true - ID string `json:"Id"` - - // Warnings encountered when creating the container - // Required: true - Warnings []string `json:"Warnings"` -} 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 63381da3674..00000000000 --- 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 c10f175ea82..00000000000 --- 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/container_wait.go b/vendor/github.com/docker/docker/api/types/container/container_wait.go deleted file mode 100644 index 49e05ae6694..00000000000 --- a/vendor/github.com/docker/docker/api/types/container/container_wait.go +++ /dev/null @@ -1,28 +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 -// ---------------------------------------------------------------------------- - -// ContainerWaitOKBodyError container waiting error, if any -// swagger:model ContainerWaitOKBodyError -type ContainerWaitOKBodyError struct { - - // Details of an error - Message string `json:"Message,omitempty"` -} - -// ContainerWaitOKBody OK response to ContainerWait operation -// swagger:model ContainerWaitOKBody -type ContainerWaitOKBody struct { - - // error - // Required: true - Error *ContainerWaitOKBodyError `json:"Error"` - - // Exit code of the container - // Required: true - StatusCode int64 `json:"StatusCode"` -} diff --git a/vendor/github.com/docker/docker/api/types/container/host_config.go b/vendor/github.com/docker/docker/api/types/container/host_config.go deleted file mode 100644 index 2d1cbaa9abd..00000000000 --- a/vendor/github.com/docker/docker/api/types/container/host_config.go +++ /dev/null @@ -1,447 +0,0 @@ -package container // import "github.com/docker/docker/api/types/container" - -import ( - "strings" - - "github.com/docker/docker/api/types/blkiodev" - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/strslice" - "github.com/docker/go-connections/nat" - units "github.com/docker/go-units" -) - -// CgroupnsMode represents the cgroup namespace mode of the container -type CgroupnsMode string - -// IsPrivate indicates whether the container uses its own private cgroup namespace -func (c CgroupnsMode) IsPrivate() bool { - return c == "private" -} - -// IsHost indicates whether the container shares the host's cgroup namespace -func (c CgroupnsMode) IsHost() bool { - return c == "host" -} - -// IsEmpty indicates whether the container cgroup namespace mode is unset -func (c CgroupnsMode) IsEmpty() bool { - return c == "" -} - -// Valid indicates whether the cgroup namespace mode is valid -func (c CgroupnsMode) Valid() bool { - return c.IsEmpty() || c.IsPrivate() || c.IsHost() -} - -// Isolation represents the isolation technology of a container. The supported -// values are platform specific -type Isolation string - -// IsDefault indicates the default isolation technology of a container. On Linux this -// is the native driver. On Windows, this is a Windows Server Container. -func (i Isolation) IsDefault() bool { - return strings.ToLower(string(i)) == "default" || string(i) == "" -} - -// IsHyperV indicates the use of a Hyper-V partition for isolation -func (i Isolation) IsHyperV() bool { - return strings.ToLower(string(i)) == "hyperv" -} - -// IsProcess indicates the use of process isolation -func (i Isolation) IsProcess() bool { - return strings.ToLower(string(i)) == "process" -} - -const ( - // IsolationEmpty is unspecified (same behavior as default) - IsolationEmpty = Isolation("") - // IsolationDefault is the default isolation mode on current daemon - IsolationDefault = Isolation("default") - // IsolationProcess is process isolation mode - IsolationProcess = Isolation("process") - // IsolationHyperV is HyperV isolation mode - IsolationHyperV = Isolation("hyperv") -) - -// IpcMode represents the container ipc stack. -type IpcMode string - -// IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared. -func (n IpcMode) IsPrivate() bool { - return n == "private" -} - -// IsHost indicates whether the container shares the host's ipc namespace. -func (n IpcMode) IsHost() bool { - return n == "host" -} - -// IsShareable indicates whether the container's ipc namespace can be shared with another container. -func (n IpcMode) IsShareable() bool { - return n == "shareable" -} - -// IsContainer indicates whether the container uses another container's ipc namespace. -func (n IpcMode) IsContainer() bool { - parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" -} - -// IsNone indicates whether container IpcMode is set to "none". -func (n IpcMode) IsNone() bool { - return n == "none" -} - -// IsEmpty indicates whether container IpcMode is empty -func (n IpcMode) IsEmpty() bool { - return n == "" -} - -// Valid indicates whether the ipc mode is valid. -func (n IpcMode) Valid() bool { - return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer() -} - -// Container returns the name of the container ipc stack is going to be used. -func (n IpcMode) Container() string { - parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 && parts[0] == "container" { - return parts[1] - } - return "" -} - -// NetworkMode represents the container network stack. -type NetworkMode string - -// IsNone indicates whether container isn't using a network stack. -func (n NetworkMode) IsNone() bool { - return n == "none" -} - -// IsDefault indicates whether container uses the default network stack. -func (n NetworkMode) IsDefault() bool { - return n == "default" -} - -// IsPrivate indicates whether container uses its private network stack. -func (n NetworkMode) IsPrivate() bool { - return !(n.IsHost() || n.IsContainer()) -} - -// IsContainer indicates whether container uses a container network stack. -func (n NetworkMode) IsContainer() bool { - parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" -} - -// ConnectedContainer is the id of the container which network this container is connected to. -func (n NetworkMode) ConnectedContainer() string { - parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { - return parts[1] - } - return "" -} - -// UserDefined indicates user-created network -func (n NetworkMode) UserDefined() string { - if n.IsUserDefined() { - return string(n) - } - return "" -} - -// UsernsMode represents userns mode in the container. -type UsernsMode string - -// IsHost indicates whether the container uses the host's userns. -func (n UsernsMode) IsHost() bool { - return n == "host" -} - -// IsPrivate indicates whether the container uses the a private userns. -func (n UsernsMode) IsPrivate() bool { - return !(n.IsHost()) -} - -// Valid indicates whether the userns is valid. -func (n UsernsMode) Valid() bool { - parts := strings.Split(string(n), ":") - switch mode := parts[0]; mode { - case "", "host": - default: - return false - } - return true -} - -// CgroupSpec represents the cgroup to use for the container. -type CgroupSpec string - -// IsContainer indicates whether the container is using another container cgroup -func (c CgroupSpec) IsContainer() bool { - parts := strings.SplitN(string(c), ":", 2) - return len(parts) > 1 && parts[0] == "container" -} - -// Valid indicates whether the cgroup spec is valid. -func (c CgroupSpec) Valid() bool { - return c.IsContainer() || c == "" -} - -// Container returns the name of the container whose cgroup will be used. -func (c CgroupSpec) Container() string { - parts := strings.SplitN(string(c), ":", 2) - if len(parts) > 1 { - return parts[1] - } - return "" -} - -// UTSMode represents the UTS namespace of the container. -type UTSMode string - -// IsPrivate indicates whether the container uses its private UTS namespace. -func (n UTSMode) IsPrivate() bool { - return !(n.IsHost()) -} - -// IsHost indicates whether the container uses the host's UTS namespace. -func (n UTSMode) IsHost() bool { - return n == "host" -} - -// Valid indicates whether the UTS namespace is valid. -func (n UTSMode) Valid() bool { - parts := strings.Split(string(n), ":") - switch mode := parts[0]; mode { - case "", "host": - default: - return false - } - return true -} - -// PidMode represents the pid namespace of the container. -type PidMode string - -// IsPrivate indicates whether the container uses its own new pid namespace. -func (n PidMode) IsPrivate() bool { - return !(n.IsHost() || n.IsContainer()) -} - -// IsHost indicates whether the container uses the host's pid namespace. -func (n PidMode) IsHost() bool { - return n == "host" -} - -// IsContainer indicates whether the container uses a container's pid namespace. -func (n PidMode) IsContainer() bool { - parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" -} - -// Valid indicates whether the pid namespace is valid. -func (n PidMode) Valid() bool { - parts := strings.Split(string(n), ":") - switch mode := parts[0]; mode { - case "", "host": - case "container": - if len(parts) != 2 || parts[1] == "" { - return false - } - default: - return false - } - return true -} - -// Container returns the name of the container whose pid namespace is going to be used. -func (n PidMode) Container() string { - parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { - return parts[1] - } - return "" -} - -// DeviceRequest represents a request for devices from a device driver. -// Used by GPU device drivers. -type DeviceRequest struct { - Driver string // Name of device driver - Count int // Number of devices to request (-1 = All) - DeviceIDs []string // List of device IDs as recognizable by the device driver - Capabilities [][]string // An OR list of AND lists of device capabilities (e.g. "gpu") - Options map[string]string // Options to pass onto the device driver -} - -// DeviceMapping represents the device mapping between the host and the container. -type DeviceMapping struct { - PathOnHost string - PathInContainer string - CgroupPermissions string -} - -// RestartPolicy represents the restart policies of the container. -type RestartPolicy struct { - Name string - MaximumRetryCount int -} - -// IsNone indicates whether the container has the "no" restart policy. -// This means the container will not automatically restart when exiting. -func (rp *RestartPolicy) IsNone() bool { - return rp.Name == "no" || rp.Name == "" -} - -// IsAlways indicates whether the container has the "always" restart policy. -// This means the container will automatically restart regardless of the exit status. -func (rp *RestartPolicy) IsAlways() bool { - return rp.Name == "always" -} - -// IsOnFailure indicates whether the container has the "on-failure" restart policy. -// This means the container will automatically restart of exiting with a non-zero exit status. -func (rp *RestartPolicy) IsOnFailure() bool { - return rp.Name == "on-failure" -} - -// IsUnlessStopped indicates whether the container has the -// "unless-stopped" restart policy. This means the container will -// automatically restart unless user has put it to stopped state. -func (rp *RestartPolicy) IsUnlessStopped() bool { - return rp.Name == "unless-stopped" -} - -// IsSame compares two RestartPolicy to see if they are the same -func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool { - return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount -} - -// LogMode is a type to define the available modes for logging -// These modes affect how logs are handled when log messages start piling up. -type LogMode string - -// Available logging modes -const ( - LogModeUnset = "" - LogModeBlocking LogMode = "blocking" - LogModeNonBlock LogMode = "non-blocking" -) - -// LogConfig represents the logging configuration of the container. -type LogConfig struct { - Type string - Config map[string]string -} - -// Resources contains container's resources (cgroups config, ulimits...) -type Resources struct { - // Applicable to all platforms - CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers) - Memory int64 // Memory limit (in bytes) - NanoCPUs int64 `json:"NanoCpus"` // CPU quota in units of 10-9 CPUs. - - // Applicable to UNIX platforms - CgroupParent string // Parent cgroup. - BlkioWeight uint16 // Block IO weight (relative weight vs. other containers) - BlkioWeightDevice []*blkiodev.WeightDevice - BlkioDeviceReadBps []*blkiodev.ThrottleDevice - BlkioDeviceWriteBps []*blkiodev.ThrottleDevice - BlkioDeviceReadIOps []*blkiodev.ThrottleDevice - BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice - CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period - CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota - CPURealtimePeriod int64 `json:"CpuRealtimePeriod"` // CPU real-time period - CPURealtimeRuntime int64 `json:"CpuRealtimeRuntime"` // CPU real-time runtime - CpusetCpus string // CpusetCpus 0-2, 0,1 - CpusetMems string // CpusetMems 0-2, 0,1 - Devices []DeviceMapping // List of devices to map inside the container - DeviceCgroupRules []string // List of rule to be added to the device cgroup - DeviceRequests []DeviceRequest // List of device requests for device drivers - KernelMemory int64 // Kernel memory limit (in bytes), Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes - KernelMemoryTCP int64 // Hard limit for kernel TCP buffer memory (in bytes) - MemoryReservation int64 // Memory soft limit (in bytes) - MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap - MemorySwappiness *int64 // Tuning container memory swappiness behaviour - OomKillDisable *bool // Whether to disable OOM Killer or not - PidsLimit *int64 // Setting PIDs limit for a container; Set `0` or `-1` for unlimited, or `null` to not change. - Ulimits []*units.Ulimit // List of ulimits to be set in the container - - // Applicable to Windows - CPUCount int64 `json:"CpuCount"` // CPU count - CPUPercent int64 `json:"CpuPercent"` // CPU percent - IOMaximumIOps uint64 // Maximum IOps for the container system drive - IOMaximumBandwidth uint64 // Maximum IO in bytes per second for the container system drive -} - -// UpdateConfig holds the mutable attributes of a Container. -// Those attributes can be updated at runtime. -type UpdateConfig struct { - // Contains container's resources (cgroups, ulimits) - Resources - RestartPolicy RestartPolicy -} - -// HostConfig the non-portable Config structure of a container. -// Here, "non-portable" means "dependent of the host we are running on". -// Portable information *should* appear in Config. -type HostConfig struct { - // Applicable to all platforms - Binds []string // List of volume bindings for this container - ContainerIDFile string // File (path) where the containerId is written - LogConfig LogConfig // Configuration of the logs for this container - NetworkMode NetworkMode // Network mode to use for the container - PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host - RestartPolicy RestartPolicy // Restart policy to be used for the container - AutoRemove bool // Automatically remove container when it exits - VolumeDriver string // Name of the volume driver used to mount volumes - VolumesFrom []string // List of volumes to take from other container - - // Applicable to UNIX platforms - CapAdd strslice.StrSlice // List of kernel capabilities to add to the container - CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container - CgroupnsMode CgroupnsMode // Cgroup namespace mode to use for the container - DNS []string `json:"Dns"` // List of DNS server to lookup - DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for - DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for - ExtraHosts []string // List of extra hosts - GroupAdd []string // List of additional groups that the container process will run as - IpcMode IpcMode // IPC namespace to use for the container - Cgroup CgroupSpec // Cgroup to use for the container - Links []string // List of links (in the name:alias form) - OomScoreAdj int // Container preference for OOM-killing - PidMode PidMode // PID namespace to use for the container - Privileged bool // Is the container in privileged mode - PublishAllPorts bool // Should docker publish all exposed port for the container - ReadonlyRootfs bool // Is the container root filesystem in read-only - SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux. - StorageOpt map[string]string `json:",omitempty"` // Storage driver options per container. - Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container - UTSMode UTSMode // UTS namespace to use for the container - UsernsMode UsernsMode // The user namespace to use for the container - ShmSize int64 // Total shm memory usage - Sysctls map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container - Runtime string `json:",omitempty"` // Runtime to use with this container - - // Applicable to Windows - ConsoleSize [2]uint // Initial console size (height,width) - Isolation Isolation // Isolation technology of the container (e.g. default, hyperv) - - // Contains container's resources (cgroups, ulimits) - Resources - - // Mounts specs used by the container - Mounts []mount.Mount `json:",omitempty"` - - // MaskedPaths is the list of paths to be masked inside the container (this overrides the default set of paths) - MaskedPaths []string - - // ReadonlyPaths is the list of paths to be set as read-only inside the container (this overrides the default set of paths) - ReadonlyPaths []string - - // Run a custom init inside the container, if null, use the daemon's configured settings - Init *bool `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go b/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go deleted file mode 100644 index cf6fdf44026..00000000000 --- a/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go +++ /dev/null @@ -1,41 +0,0 @@ -// +build !windows - -package container // import "github.com/docker/docker/api/types/container" - -// IsValid indicates if an isolation technology is valid -func (i Isolation) IsValid() bool { - return i.IsDefault() -} - -// NetworkName returns the name of the network stack. -func (n NetworkMode) NetworkName() string { - if n.IsBridge() { - return "bridge" - } else if n.IsHost() { - return "host" - } else if n.IsContainer() { - return "container" - } else if n.IsNone() { - return "none" - } else if n.IsDefault() { - return "default" - } else if n.IsUserDefined() { - return n.UserDefined() - } - return "" -} - -// IsBridge indicates whether container uses the bridge network stack -func (n NetworkMode) IsBridge() bool { - return n == "bridge" -} - -// IsHost indicates whether container uses the host network stack. -func (n NetworkMode) IsHost() bool { - return n == "host" -} - -// IsUserDefined indicates user-created network -func (n NetworkMode) IsUserDefined() bool { - return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer() -} diff --git a/vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go b/vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go deleted file mode 100644 index 99f803a5bb1..00000000000 --- a/vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go +++ /dev/null @@ -1,40 +0,0 @@ -package container // import "github.com/docker/docker/api/types/container" - -// IsBridge indicates whether container uses the bridge network stack -// in windows it is given the name NAT -func (n NetworkMode) IsBridge() bool { - return n == "nat" -} - -// IsHost indicates whether container uses the host network stack. -// returns false as this is not supported by windows -func (n NetworkMode) IsHost() bool { - return false -} - -// IsUserDefined indicates user-created network -func (n NetworkMode) IsUserDefined() bool { - return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer() -} - -// IsValid indicates if an isolation technology is valid -func (i Isolation) IsValid() bool { - return i.IsDefault() || i.IsHyperV() || i.IsProcess() -} - -// NetworkName returns the name of the network stack. -func (n NetworkMode) NetworkName() string { - if n.IsDefault() { - return "default" - } else if n.IsBridge() { - return "nat" - } else if n.IsNone() { - return "none" - } else if n.IsContainer() { - return "container" - } else if n.IsUserDefined() { - return n.UserDefined() - } - - return "" -} diff --git a/vendor/github.com/docker/docker/api/types/container/waitcondition.go b/vendor/github.com/docker/docker/api/types/container/waitcondition.go deleted file mode 100644 index cd8311f99cf..00000000000 --- a/vendor/github.com/docker/docker/api/types/container/waitcondition.go +++ /dev/null @@ -1,22 +0,0 @@ -package container // import "github.com/docker/docker/api/types/container" - -// WaitCondition is a type used to specify a container state for which -// to wait. -type WaitCondition string - -// Possible WaitCondition Values. -// -// WaitConditionNotRunning (default) is used to wait for any of the non-running -// states: "created", "exited", "dead", "removing", or "removed". -// -// WaitConditionNextExit is used to wait for the next time the state changes -// to a non-running state. If the state is currently "created" or "exited", -// this would cause Wait() to block until either the container runs and exits -// or is removed. -// -// WaitConditionRemoved is used to wait for the container to be removed. -const ( - WaitConditionNotRunning WaitCondition = "not-running" - WaitConditionNextExit WaitCondition = "next-exit" - WaitConditionRemoved WaitCondition = "removed" -) diff --git a/vendor/github.com/docker/docker/api/types/error_response.go b/vendor/github.com/docker/docker/api/types/error_response.go deleted file mode 100644 index dc942d9d9ef..00000000000 --- a/vendor/github.com/docker/docker/api/types/error_response.go +++ /dev/null @@ -1,13 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// ErrorResponse Represents an error. -// swagger:model ErrorResponse -type ErrorResponse struct { - - // The error message. - // Required: true - Message string `json:"message"` -} diff --git a/vendor/github.com/docker/docker/api/types/error_response_ext.go b/vendor/github.com/docker/docker/api/types/error_response_ext.go deleted file mode 100644 index f84f034cd54..00000000000 --- a/vendor/github.com/docker/docker/api/types/error_response_ext.go +++ /dev/null @@ -1,6 +0,0 @@ -package types - -// Error returns the error message -func (e ErrorResponse) Error() string { - return e.Message -} diff --git a/vendor/github.com/docker/docker/api/types/events/events.go b/vendor/github.com/docker/docker/api/types/events/events.go deleted file mode 100644 index aa8fba81548..00000000000 --- a/vendor/github.com/docker/docker/api/types/events/events.go +++ /dev/null @@ -1,54 +0,0 @@ -package events // import "github.com/docker/docker/api/types/events" - -const ( - // BuilderEventType is the event type that the builder generates - BuilderEventType = "builder" - // ContainerEventType is the event type that containers generate - ContainerEventType = "container" - // DaemonEventType is the event type that daemon generate - DaemonEventType = "daemon" - // ImageEventType is the event type that images generate - ImageEventType = "image" - // NetworkEventType is the event type that networks generate - NetworkEventType = "network" - // PluginEventType is the event type that plugins generate - PluginEventType = "plugin" - // VolumeEventType is the event type that volumes generate - VolumeEventType = "volume" - // ServiceEventType is the event type that services generate - ServiceEventType = "service" - // NodeEventType is the event type that nodes generate - NodeEventType = "node" - // SecretEventType is the event type that secrets generate - SecretEventType = "secret" - // ConfigEventType is the event type that configs generate - ConfigEventType = "config" -) - -// Actor describes something that generates events, -// like a container, or a network, or a volume. -// It has a defined name and a set or attributes. -// The container attributes are its labels, other actors -// can generate these attributes from other properties. -type Actor struct { - ID string - Attributes map[string]string -} - -// Message represents the information an event contains -type Message struct { - // Deprecated information from JSONMessage. - // With data only in container events. - Status string `json:"status,omitempty"` - ID string `json:"id,omitempty"` - From string `json:"from,omitempty"` - - Type string - Action string - Actor Actor - // Engine events are local scope. Cluster events are swarm scope. - Scope string `json:"scope,omitempty"` - - Time int64 `json:"time,omitempty"` - TimeNano int64 `json:"timeNano,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/filters/parse.go b/vendor/github.com/docker/docker/api/types/filters/parse.go deleted file mode 100644 index 4bc91cffd6e..00000000000 --- a/vendor/github.com/docker/docker/api/types/filters/parse.go +++ /dev/null @@ -1,324 +0,0 @@ -/*Package filters provides tools for encoding a mapping of keys to a set of -multiple values. -*/ -package filters // import "github.com/docker/docker/api/types/filters" - -import ( - "encoding/json" - "regexp" - "strings" - - "github.com/docker/docker/api/types/versions" -) - -// Args stores a mapping of keys to a set of multiple values. -type Args struct { - fields map[string]map[string]bool -} - -// KeyValuePair are used to initialize a new Args -type KeyValuePair struct { - Key string - Value string -} - -// Arg creates a new KeyValuePair for initializing Args -func Arg(key, value string) KeyValuePair { - return KeyValuePair{Key: key, Value: value} -} - -// NewArgs returns a new Args populated with the initial args -func NewArgs(initialArgs ...KeyValuePair) Args { - args := Args{fields: map[string]map[string]bool{}} - for _, arg := range initialArgs { - args.Add(arg.Key, arg.Value) - } - return args -} - -// Keys returns all the keys in list of Args -func (args Args) Keys() []string { - keys := make([]string, 0, len(args.fields)) - for k := range args.fields { - keys = append(keys, k) - } - return keys -} - -// MarshalJSON returns a JSON byte representation of the Args -func (args Args) MarshalJSON() ([]byte, error) { - if len(args.fields) == 0 { - return []byte{}, nil - } - return json.Marshal(args.fields) -} - -// ToJSON returns the Args as a JSON encoded string -func ToJSON(a Args) (string, error) { - if a.Len() == 0 { - return "", nil - } - buf, err := json.Marshal(a) - return string(buf), err -} - -// ToParamWithVersion encodes Args as a JSON string. If version is less than 1.22 -// then the encoded format will use an older legacy format where the values are a -// list of strings, instead of a set. -// -// Deprecated: do not use in any new code; use ToJSON instead -func ToParamWithVersion(version string, a Args) (string, error) { - if a.Len() == 0 { - return "", nil - } - - if version != "" && versions.LessThan(version, "1.22") { - buf, err := json.Marshal(convertArgsToSlice(a.fields)) - return string(buf), err - } - - return ToJSON(a) -} - -// FromJSON decodes a JSON encoded string into Args -func FromJSON(p string) (Args, error) { - args := NewArgs() - - if p == "" { - return args, nil - } - - raw := []byte(p) - err := json.Unmarshal(raw, &args) - if err == nil { - return args, nil - } - - // Fallback to parsing arguments in the legacy slice format - deprecated := map[string][]string{} - if legacyErr := json.Unmarshal(raw, &deprecated); legacyErr != nil { - return args, err - } - - args.fields = deprecatedArgs(deprecated) - return args, nil -} - -// UnmarshalJSON populates the Args from JSON encode bytes -func (args Args) UnmarshalJSON(raw []byte) error { - if len(raw) == 0 { - return nil - } - return json.Unmarshal(raw, &args.fields) -} - -// Get returns the list of values associated with the key -func (args Args) Get(key string) []string { - values := args.fields[key] - if values == nil { - return make([]string, 0) - } - slice := make([]string, 0, len(values)) - for key := range values { - slice = append(slice, key) - } - return slice -} - -// Add a new value to the set of values -func (args Args) Add(key, value string) { - if _, ok := args.fields[key]; ok { - args.fields[key][value] = true - } else { - args.fields[key] = map[string]bool{value: true} - } -} - -// Del removes a value from the set -func (args Args) Del(key, value string) { - if _, ok := args.fields[key]; ok { - delete(args.fields[key], value) - if len(args.fields[key]) == 0 { - delete(args.fields, key) - } - } -} - -// Len returns the number of keys in the mapping -func (args Args) Len() int { - return len(args.fields) -} - -// MatchKVList returns true if all the pairs in sources exist as key=value -// pairs in the mapping at key, or if there are no values at key. -func (args Args) MatchKVList(key string, sources map[string]string) bool { - fieldValues := args.fields[key] - - // do not filter if there is no filter set or cannot determine filter - if len(fieldValues) == 0 { - return true - } - - if len(sources) == 0 { - return false - } - - for value := range fieldValues { - testKV := strings.SplitN(value, "=", 2) - - v, ok := sources[testKV[0]] - if !ok { - return false - } - if len(testKV) == 2 && testKV[1] != v { - return false - } - } - - return true -} - -// Match returns true if any of the values at key match the source string -func (args Args) Match(field, source string) bool { - if args.ExactMatch(field, source) { - return true - } - - fieldValues := args.fields[field] - for name2match := range fieldValues { - match, err := regexp.MatchString(name2match, source) - if err != nil { - continue - } - if match { - return true - } - } - return false -} - -// ExactMatch returns true if the source matches exactly one of the values. -func (args Args) ExactMatch(key, source string) bool { - fieldValues, ok := args.fields[key] - // do not filter if there is no filter set or cannot determine filter - if !ok || len(fieldValues) == 0 { - return true - } - - // try to match full name value to avoid O(N) regular expression matching - return fieldValues[source] -} - -// UniqueExactMatch returns true if there is only one value and the source -// matches exactly the value. -func (args Args) UniqueExactMatch(key, source string) bool { - fieldValues := args.fields[key] - // do not filter if there is no filter set or cannot determine filter - if len(fieldValues) == 0 { - return true - } - if len(args.fields[key]) != 1 { - return false - } - - // try to match full name value to avoid O(N) regular expression matching - return fieldValues[source] -} - -// FuzzyMatch returns true if the source matches exactly one value, or the -// source has one of the values as a prefix. -func (args Args) FuzzyMatch(key, source string) bool { - if args.ExactMatch(key, source) { - return true - } - - fieldValues := args.fields[key] - for prefix := range fieldValues { - if strings.HasPrefix(source, prefix) { - return true - } - } - return false -} - -// Contains returns true if the key exists in the mapping -func (args Args) Contains(field string) bool { - _, ok := args.fields[field] - return ok -} - -type invalidFilter string - -func (e invalidFilter) Error() string { - return "Invalid filter '" + string(e) + "'" -} - -func (invalidFilter) InvalidParameter() {} - -// Validate compared the set of accepted keys against the keys in the mapping. -// An error is returned if any mapping keys are not in the accepted set. -func (args Args) Validate(accepted map[string]bool) error { - for name := range args.fields { - if !accepted[name] { - return invalidFilter(name) - } - } - return nil -} - -// WalkValues iterates over the list of values for a key in the mapping and calls -// op() for each value. If op returns an error the iteration stops and the -// error is returned. -func (args Args) WalkValues(field string, op func(value string) error) error { - if _, ok := args.fields[field]; !ok { - return nil - } - for v := range args.fields[field] { - if err := op(v); err != nil { - return err - } - } - return nil -} - -// Clone returns a copy of args. -func (args Args) Clone() (newArgs Args) { - newArgs.fields = make(map[string]map[string]bool, len(args.fields)) - for k, m := range args.fields { - var mm map[string]bool - if m != nil { - mm = make(map[string]bool, len(m)) - for kk, v := range m { - mm[kk] = v - } - } - newArgs.fields[k] = mm - } - return newArgs -} - -func deprecatedArgs(d map[string][]string) map[string]map[string]bool { - m := map[string]map[string]bool{} - for k, v := range d { - values := map[string]bool{} - for _, vv := range v { - values[vv] = true - } - m[k] = values - } - return m -} - -func convertArgsToSlice(f map[string]map[string]bool) map[string][]string { - m := map[string][]string{} - for k, v := range f { - values := []string{} - for kk := range v { - if v[kk] { - values = append(values, kk) - } - } - m[k] = values - } - return m -} diff --git a/vendor/github.com/docker/docker/api/types/graph_driver_data.go b/vendor/github.com/docker/docker/api/types/graph_driver_data.go deleted file mode 100644 index 4d9bf1c62c8..00000000000 --- a/vendor/github.com/docker/docker/api/types/graph_driver_data.go +++ /dev/null @@ -1,17 +0,0 @@ -package types - -// 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 a container's graph driver. -// swagger:model GraphDriverData -type GraphDriverData struct { - - // data - // Required: true - Data map[string]string `json:"Data"` - - // name - // Required: true - Name string `json:"Name"` -} diff --git a/vendor/github.com/docker/docker/api/types/id_response.go b/vendor/github.com/docker/docker/api/types/id_response.go deleted file mode 100644 index 7592d2f8b15..00000000000 --- a/vendor/github.com/docker/docker/api/types/id_response.go +++ /dev/null @@ -1,13 +0,0 @@ -package types - -// 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 -type IDResponse struct { - - // The id of the newly created object. - // Required: true - ID string `json:"Id"` -} diff --git a/vendor/github.com/docker/docker/api/types/image/image_history.go b/vendor/github.com/docker/docker/api/types/image/image_history.go deleted file mode 100644 index e302bb0aebb..00000000000 --- a/vendor/github.com/docker/docker/api/types/image/image_history.go +++ /dev/null @@ -1,36 +0,0 @@ -package image // import "github.com/docker/docker/api/types/image" - -// ---------------------------------------------------------------------------- -// Code generated by `swagger generate operation`. DO NOT EDIT. -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -// HistoryResponseItem individual image layer information in response to ImageHistory operation -// swagger:model HistoryResponseItem -type HistoryResponseItem struct { - - // comment - // Required: true - Comment string `json:"Comment"` - - // created - // Required: true - Created int64 `json:"Created"` - - // created by - // Required: true - CreatedBy string `json:"CreatedBy"` - - // Id - // Required: true - ID string `json:"Id"` - - // size - // Required: true - Size int64 `json:"Size"` - - // tags - // Required: true - Tags []string `json:"Tags"` -} diff --git a/vendor/github.com/docker/docker/api/types/image_delete_response_item.go b/vendor/github.com/docker/docker/api/types/image_delete_response_item.go deleted file mode 100644 index b9a65a0d8e8..00000000000 --- a/vendor/github.com/docker/docker/api/types/image_delete_response_item.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// ImageDeleteResponseItem image delete response item -// swagger:model ImageDeleteResponseItem -type ImageDeleteResponseItem struct { - - // The image ID of an image that was deleted - Deleted string `json:"Deleted,omitempty"` - - // The image ID of an image that was untagged - Untagged string `json:"Untagged,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/image_summary.go b/vendor/github.com/docker/docker/api/types/image_summary.go deleted file mode 100644 index e145b3dcfcd..00000000000 --- a/vendor/github.com/docker/docker/api/types/image_summary.go +++ /dev/null @@ -1,49 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// ImageSummary image summary -// swagger:model ImageSummary -type ImageSummary struct { - - // containers - // Required: true - Containers int64 `json:"Containers"` - - // created - // Required: true - Created int64 `json:"Created"` - - // Id - // Required: true - ID string `json:"Id"` - - // labels - // Required: true - Labels map[string]string `json:"Labels"` - - // parent Id - // Required: true - ParentID string `json:"ParentId"` - - // repo digests - // Required: true - RepoDigests []string `json:"RepoDigests"` - - // repo tags - // Required: true - RepoTags []string `json:"RepoTags"` - - // shared size - // Required: true - SharedSize int64 `json:"SharedSize"` - - // size - // Required: true - Size int64 `json:"Size"` - - // virtual size - // Required: true - VirtualSize int64 `json:"VirtualSize"` -} diff --git a/vendor/github.com/docker/docker/api/types/mount/mount.go b/vendor/github.com/docker/docker/api/types/mount/mount.go deleted file mode 100644 index 443b8d07a9f..00000000000 --- a/vendor/github.com/docker/docker/api/types/mount/mount.go +++ /dev/null @@ -1,131 +0,0 @@ -package mount // import "github.com/docker/docker/api/types/mount" - -import ( - "os" -) - -// Type represents the type of a mount. -type Type string - -// Type constants -const ( - // TypeBind is the type for mounting host dir - TypeBind Type = "bind" - // TypeVolume is the type for remote storage volumes - TypeVolume Type = "volume" - // TypeTmpfs is the type for mounting tmpfs - TypeTmpfs Type = "tmpfs" - // TypeNamedPipe is the type for mounting Windows named pipes - TypeNamedPipe Type = "npipe" -) - -// Mount represents a mount (volume). -type Mount struct { - Type Type `json:",omitempty"` - // Source specifies the name of the mount. Depending on mount type, this - // may be a volume name or a host path, or even ignored. - // Source is not supported for tmpfs (must be an empty value) - Source string `json:",omitempty"` - Target string `json:",omitempty"` - ReadOnly bool `json:",omitempty"` - Consistency Consistency `json:",omitempty"` - - BindOptions *BindOptions `json:",omitempty"` - VolumeOptions *VolumeOptions `json:",omitempty"` - TmpfsOptions *TmpfsOptions `json:",omitempty"` -} - -// Propagation represents the propagation of a mount. -type Propagation string - -const ( - // PropagationRPrivate RPRIVATE - PropagationRPrivate Propagation = "rprivate" - // PropagationPrivate PRIVATE - PropagationPrivate Propagation = "private" - // PropagationRShared RSHARED - PropagationRShared Propagation = "rshared" - // PropagationShared SHARED - PropagationShared Propagation = "shared" - // PropagationRSlave RSLAVE - PropagationRSlave Propagation = "rslave" - // PropagationSlave SLAVE - PropagationSlave Propagation = "slave" -) - -// Propagations is the list of all valid mount propagations -var Propagations = []Propagation{ - PropagationRPrivate, - PropagationPrivate, - PropagationRShared, - PropagationShared, - PropagationRSlave, - PropagationSlave, -} - -// Consistency represents the consistency requirements of a mount. -type Consistency string - -const ( - // ConsistencyFull guarantees bind mount-like consistency - ConsistencyFull Consistency = "consistent" - // ConsistencyCached mounts can cache read data and FS structure - ConsistencyCached Consistency = "cached" - // ConsistencyDelegated mounts can cache read and written data and structure - ConsistencyDelegated Consistency = "delegated" - // ConsistencyDefault provides "consistent" behavior unless overridden - ConsistencyDefault Consistency = "default" -) - -// BindOptions defines options specific to mounts of type "bind". -type BindOptions struct { - Propagation Propagation `json:",omitempty"` - NonRecursive bool `json:",omitempty"` -} - -// VolumeOptions represents the options for a mount of type volume. -type VolumeOptions struct { - NoCopy bool `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - DriverConfig *Driver `json:",omitempty"` -} - -// Driver represents a volume driver. -type Driver struct { - Name string `json:",omitempty"` - Options map[string]string `json:",omitempty"` -} - -// TmpfsOptions defines options specific to mounts of type "tmpfs". -type TmpfsOptions struct { - // Size sets the size of the tmpfs, in bytes. - // - // This will be converted to an operating system specific value - // depending on the host. For example, on linux, it will be converted to - // use a 'k', 'm' or 'g' syntax. BSD, though not widely supported with - // docker, uses a straight byte value. - // - // Percentages are not supported. - SizeBytes int64 `json:",omitempty"` - // Mode of the tmpfs upon creation - Mode os.FileMode `json:",omitempty"` - - // TODO(stevvooe): There are several more tmpfs flags, specified in the - // daemon, that are accepted. Only the most basic are added for now. - // - // From https://github.com/moby/sys/blob/mount/v0.1.1/mount/flags.go#L47-L56 - // - // var validFlags = map[string]bool{ - // "": true, - // "size": true, X - // "mode": true, X - // "uid": true, - // "gid": true, - // "nr_inodes": true, - // "nr_blocks": true, - // "mpol": true, - // } - // - // Some of these may be straightforward to add, but others, such as - // uid/gid have implications in a clustered system. -} diff --git a/vendor/github.com/docker/docker/api/types/network/network.go b/vendor/github.com/docker/docker/api/types/network/network.go deleted file mode 100644 index 437b184c67b..00000000000 --- a/vendor/github.com/docker/docker/api/types/network/network.go +++ /dev/null @@ -1,126 +0,0 @@ -package network // import "github.com/docker/docker/api/types/network" -import ( - "github.com/docker/docker/api/types/filters" -) - -// Address represents an IP address -type Address struct { - Addr string - PrefixLen int -} - -// IPAM represents IP Address Management -type IPAM struct { - Driver string - Options map[string]string // Per network IPAM driver options - Config []IPAMConfig -} - -// IPAMConfig represents IPAM configurations -type IPAMConfig struct { - Subnet string `json:",omitempty"` - IPRange string `json:",omitempty"` - Gateway string `json:",omitempty"` - AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"` -} - -// EndpointIPAMConfig represents IPAM configurations for the endpoint -type EndpointIPAMConfig struct { - IPv4Address string `json:",omitempty"` - IPv6Address string `json:",omitempty"` - LinkLocalIPs []string `json:",omitempty"` -} - -// Copy makes a copy of the endpoint ipam config -func (cfg *EndpointIPAMConfig) Copy() *EndpointIPAMConfig { - cfgCopy := *cfg - cfgCopy.LinkLocalIPs = make([]string, 0, len(cfg.LinkLocalIPs)) - cfgCopy.LinkLocalIPs = append(cfgCopy.LinkLocalIPs, cfg.LinkLocalIPs...) - return &cfgCopy -} - -// PeerInfo represents one peer of an overlay network -type PeerInfo struct { - Name string - IP string -} - -// EndpointSettings stores the network endpoint details -type EndpointSettings struct { - // Configurations - IPAMConfig *EndpointIPAMConfig - Links []string - Aliases []string - // Operational data - NetworkID string - EndpointID string - Gateway string - IPAddress string - IPPrefixLen int - IPv6Gateway string - GlobalIPv6Address string - GlobalIPv6PrefixLen int - MacAddress string - DriverOpts map[string]string -} - -// Task carries the information about one backend task -type Task struct { - Name string - EndpointID string - EndpointIP string - Info map[string]string -} - -// ServiceInfo represents service parameters with the list of service's tasks -type ServiceInfo struct { - VIP string - Ports []string - LocalLBIndex int - Tasks []Task -} - -// Copy makes a deep copy of `EndpointSettings` -func (es *EndpointSettings) Copy() *EndpointSettings { - epCopy := *es - if es.IPAMConfig != nil { - epCopy.IPAMConfig = es.IPAMConfig.Copy() - } - - if es.Links != nil { - links := make([]string, 0, len(es.Links)) - epCopy.Links = append(links, es.Links...) - } - - if es.Aliases != nil { - aliases := make([]string, 0, len(es.Aliases)) - epCopy.Aliases = append(aliases, es.Aliases...) - } - return &epCopy -} - -// NetworkingConfig represents the container's networking configuration for each of its interfaces -// Carries the networking configs specified in the `docker run` and `docker network connect` commands -type NetworkingConfig struct { - EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each connecting network -} - -// ConfigReference specifies the source which provides a network's configuration -type ConfigReference struct { - Network string -} - -var acceptedFilters = map[string]bool{ - "dangling": true, - "driver": true, - "id": true, - "label": true, - "name": true, - "scope": true, - "type": true, -} - -// ValidateFilters validates the list of filter args with the available filters. -func ValidateFilters(filter filters.Args) error { - return filter.Validate(acceptedFilters) -} diff --git a/vendor/github.com/docker/docker/api/types/plugin.go b/vendor/github.com/docker/docker/api/types/plugin.go deleted file mode 100644 index abae48b9ab0..00000000000 --- a/vendor/github.com/docker/docker/api/types/plugin.go +++ /dev/null @@ -1,203 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// Plugin A plugin for the Engine API -// swagger:model Plugin -type Plugin struct { - - // config - // Required: true - Config PluginConfig `json:"Config"` - - // True if the plugin is running. False if the plugin is not running, only installed. - // Required: true - Enabled bool `json:"Enabled"` - - // Id - ID string `json:"Id,omitempty"` - - // name - // Required: true - Name string `json:"Name"` - - // plugin remote reference used to push/pull the plugin - PluginReference string `json:"PluginReference,omitempty"` - - // settings - // Required: true - Settings PluginSettings `json:"Settings"` -} - -// PluginConfig The config of a plugin. -// swagger:model PluginConfig -type PluginConfig struct { - - // args - // Required: true - Args PluginConfigArgs `json:"Args"` - - // description - // Required: true - Description string `json:"Description"` - - // Docker Version used to create the plugin - DockerVersion string `json:"DockerVersion,omitempty"` - - // documentation - // Required: true - Documentation string `json:"Documentation"` - - // entrypoint - // Required: true - Entrypoint []string `json:"Entrypoint"` - - // env - // Required: true - Env []PluginEnv `json:"Env"` - - // interface - // Required: true - Interface PluginConfigInterface `json:"Interface"` - - // ipc host - // Required: true - IpcHost bool `json:"IpcHost"` - - // linux - // Required: true - Linux PluginConfigLinux `json:"Linux"` - - // mounts - // Required: true - Mounts []PluginMount `json:"Mounts"` - - // network - // Required: true - Network PluginConfigNetwork `json:"Network"` - - // pid host - // Required: true - PidHost bool `json:"PidHost"` - - // propagated mount - // Required: true - PropagatedMount string `json:"PropagatedMount"` - - // user - User PluginConfigUser `json:"User,omitempty"` - - // work dir - // Required: true - WorkDir string `json:"WorkDir"` - - // rootfs - Rootfs *PluginConfigRootfs `json:"rootfs,omitempty"` -} - -// PluginConfigArgs plugin config args -// swagger:model PluginConfigArgs -type PluginConfigArgs struct { - - // description - // Required: true - Description string `json:"Description"` - - // name - // Required: true - Name string `json:"Name"` - - // settable - // Required: true - Settable []string `json:"Settable"` - - // value - // Required: true - Value []string `json:"Value"` -} - -// PluginConfigInterface The interface between Docker and the plugin -// swagger:model PluginConfigInterface -type PluginConfigInterface struct { - - // Protocol to use for clients connecting to the plugin. - ProtocolScheme string `json:"ProtocolScheme,omitempty"` - - // socket - // Required: true - Socket string `json:"Socket"` - - // types - // Required: true - Types []PluginInterfaceType `json:"Types"` -} - -// PluginConfigLinux plugin config linux -// swagger:model PluginConfigLinux -type PluginConfigLinux struct { - - // allow all devices - // Required: true - AllowAllDevices bool `json:"AllowAllDevices"` - - // capabilities - // Required: true - Capabilities []string `json:"Capabilities"` - - // devices - // Required: true - Devices []PluginDevice `json:"Devices"` -} - -// PluginConfigNetwork plugin config network -// swagger:model PluginConfigNetwork -type PluginConfigNetwork struct { - - // type - // Required: true - Type string `json:"Type"` -} - -// PluginConfigRootfs plugin config rootfs -// swagger:model PluginConfigRootfs -type PluginConfigRootfs struct { - - // diff ids - DiffIds []string `json:"diff_ids"` - - // type - Type string `json:"type,omitempty"` -} - -// PluginConfigUser plugin config user -// swagger:model PluginConfigUser -type PluginConfigUser struct { - - // g ID - GID uint32 `json:"GID,omitempty"` - - // UID - UID uint32 `json:"UID,omitempty"` -} - -// PluginSettings Settings that can be modified by users. -// swagger:model PluginSettings -type PluginSettings struct { - - // args - // Required: true - Args []string `json:"Args"` - - // devices - // Required: true - Devices []PluginDevice `json:"Devices"` - - // env - // Required: true - Env []string `json:"Env"` - - // mounts - // Required: true - Mounts []PluginMount `json:"Mounts"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_device.go b/vendor/github.com/docker/docker/api/types/plugin_device.go deleted file mode 100644 index 56990106755..00000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_device.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// PluginDevice plugin device -// swagger:model PluginDevice -type PluginDevice struct { - - // description - // Required: true - Description string `json:"Description"` - - // name - // Required: true - Name string `json:"Name"` - - // path - // Required: true - Path *string `json:"Path"` - - // settable - // Required: true - Settable []string `json:"Settable"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_env.go b/vendor/github.com/docker/docker/api/types/plugin_env.go deleted file mode 100644 index 32962dc2ebe..00000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_env.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// PluginEnv plugin env -// swagger:model PluginEnv -type PluginEnv struct { - - // description - // Required: true - Description string `json:"Description"` - - // name - // Required: true - Name string `json:"Name"` - - // settable - // Required: true - Settable []string `json:"Settable"` - - // value - // Required: true - Value *string `json:"Value"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_interface_type.go b/vendor/github.com/docker/docker/api/types/plugin_interface_type.go deleted file mode 100644 index c82f204e870..00000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_interface_type.go +++ /dev/null @@ -1,21 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// PluginInterfaceType plugin interface type -// swagger:model PluginInterfaceType -type PluginInterfaceType struct { - - // capability - // Required: true - Capability string `json:"Capability"` - - // prefix - // Required: true - Prefix string `json:"Prefix"` - - // version - // Required: true - Version string `json:"Version"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_mount.go b/vendor/github.com/docker/docker/api/types/plugin_mount.go deleted file mode 100644 index 5c031cf8b5c..00000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_mount.go +++ /dev/null @@ -1,37 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// PluginMount plugin mount -// swagger:model PluginMount -type PluginMount struct { - - // description - // Required: true - Description string `json:"Description"` - - // destination - // Required: true - Destination string `json:"Destination"` - - // name - // Required: true - Name string `json:"Name"` - - // options - // Required: true - Options []string `json:"Options"` - - // settable - // Required: true - Settable []string `json:"Settable"` - - // source - // Required: true - Source *string `json:"Source"` - - // type - // Required: true - Type string `json:"Type"` -} diff --git a/vendor/github.com/docker/docker/api/types/plugin_responses.go b/vendor/github.com/docker/docker/api/types/plugin_responses.go deleted file mode 100644 index 60d1fb5ad85..00000000000 --- a/vendor/github.com/docker/docker/api/types/plugin_responses.go +++ /dev/null @@ -1,71 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -import ( - "encoding/json" - "fmt" - "sort" -) - -// PluginsListResponse contains the response for the Engine API -type PluginsListResponse []*Plugin - -// UnmarshalJSON implements json.Unmarshaler for PluginInterfaceType -func (t *PluginInterfaceType) UnmarshalJSON(p []byte) error { - versionIndex := len(p) - prefixIndex := 0 - if len(p) < 2 || p[0] != '"' || p[len(p)-1] != '"' { - return fmt.Errorf("%q is not a plugin interface type", p) - } - p = p[1 : len(p)-1] -loop: - for i, b := range p { - switch b { - case '.': - prefixIndex = i - case '/': - versionIndex = i - break loop - } - } - t.Prefix = string(p[:prefixIndex]) - t.Capability = string(p[prefixIndex+1 : versionIndex]) - if versionIndex < len(p) { - t.Version = string(p[versionIndex+1:]) - } - return nil -} - -// MarshalJSON implements json.Marshaler for PluginInterfaceType -func (t *PluginInterfaceType) MarshalJSON() ([]byte, error) { - return json.Marshal(t.String()) -} - -// String implements fmt.Stringer for PluginInterfaceType -func (t PluginInterfaceType) String() string { - return fmt.Sprintf("%s.%s/%s", t.Prefix, t.Capability, t.Version) -} - -// PluginPrivilege describes a permission the user has to accept -// upon installing a plugin. -type PluginPrivilege struct { - Name string - Description string - Value []string -} - -// PluginPrivileges is a list of PluginPrivilege -type PluginPrivileges []PluginPrivilege - -func (s PluginPrivileges) Len() int { - return len(s) -} - -func (s PluginPrivileges) Less(i, j int) bool { - return s[i].Name < s[j].Name -} - -func (s PluginPrivileges) Swap(i, j int) { - sort.Strings(s[i].Value) - sort.Strings(s[j].Value) - s[i], s[j] = s[j], s[i] -} diff --git a/vendor/github.com/docker/docker/api/types/port.go b/vendor/github.com/docker/docker/api/types/port.go deleted file mode 100644 index d91234744c6..00000000000 --- a/vendor/github.com/docker/docker/api/types/port.go +++ /dev/null @@ -1,23 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// Port An open port on a container -// swagger:model Port -type Port struct { - - // Host IP address that the container's port is mapped to - IP string `json:"IP,omitempty"` - - // Port on the container - // Required: true - PrivatePort uint16 `json:"PrivatePort"` - - // Port exposed on the host - PublicPort uint16 `json:"PublicPort,omitempty"` - - // type - // Required: true - Type string `json:"Type"` -} diff --git a/vendor/github.com/docker/docker/api/types/registry/authenticate.go b/vendor/github.com/docker/docker/api/types/registry/authenticate.go deleted file mode 100644 index f0a2113e405..00000000000 --- a/vendor/github.com/docker/docker/api/types/registry/authenticate.go +++ /dev/null @@ -1,21 +0,0 @@ -package registry // import "github.com/docker/docker/api/types/registry" - -// ---------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE -// This file was generated by `swagger generate operation` -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -// AuthenticateOKBody authenticate o k body -// swagger:model AuthenticateOKBody -type AuthenticateOKBody struct { - - // An opaque token used to authenticate a user after a successful login - // Required: true - IdentityToken string `json:"IdentityToken"` - - // The status of the authentication - // Required: true - Status string `json:"Status"` -} diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go deleted file mode 100644 index 53e47084c8d..00000000000 --- a/vendor/github.com/docker/docker/api/types/registry/registry.go +++ /dev/null @@ -1,119 +0,0 @@ -package registry // import "github.com/docker/docker/api/types/registry" - -import ( - "encoding/json" - "net" - - v1 "github.com/opencontainers/image-spec/specs-go/v1" -) - -// 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 -} - -// NetIPNet is the net.IPNet type, which can be marshalled and -// unmarshalled to JSON -type NetIPNet net.IPNet - -// String returns the CIDR notation of ipnet -func (ipnet *NetIPNet) String() string { - return (*net.IPNet)(ipnet).String() -} - -// MarshalJSON returns the JSON representation of the IPNet -func (ipnet *NetIPNet) MarshalJSON() ([]byte, error) { - return json.Marshal((*net.IPNet)(ipnet).String()) -} - -// UnmarshalJSON sets the IPNet from a byte array of JSON -func (ipnet *NetIPNet) UnmarshalJSON(b []byte) (err error) { - var ipnetStr string - if err = json.Unmarshal(b, &ipnetStr); err == nil { - var cidr *net.IPNet - if _, cidr, err = net.ParseCIDR(ipnetStr); err == nil { - *ipnet = NetIPNet(*cidr) - } - } - return -} - -// IndexInfo contains information about a registry -// -// RepositoryInfo Examples: -// { -// "Index" : { -// "Name" : "docker.io", -// "Mirrors" : ["https://registry-2.docker.io/v1/", "https://registry-3.docker.io/v1/"], -// "Secure" : true, -// "Official" : true, -// }, -// "RemoteName" : "library/debian", -// "LocalName" : "debian", -// "CanonicalName" : "docker.io/debian" -// "Official" : true, -// } -// -// { -// "Index" : { -// "Name" : "127.0.0.1:5000", -// "Mirrors" : [], -// "Secure" : false, -// "Official" : false, -// }, -// "RemoteName" : "user/repo", -// "LocalName" : "127.0.0.1:5000/user/repo", -// "CanonicalName" : "127.0.0.1:5000/user/repo", -// "Official" : false, -// } -type IndexInfo struct { - // Name is the name of the registry, such as "docker.io" - Name string - // Mirrors is a list of mirrors, expressed as URIs - Mirrors []string - // Secure is set to false if the registry is part of the list of - // insecure registries. Insecure registries accept HTTP and/or accept - // HTTPS with certificates from unknown CAs. - Secure bool - // Official indicates whether this is an official registry - Official bool -} - -// SearchResult describes a search result returned from a registry -type SearchResult struct { - // StarCount indicates the number of stars this repository has - StarCount int `json:"star_count"` - // IsOfficial is true if the result is from an official repository. - IsOfficial bool `json:"is_official"` - // Name is the name of the repository - Name string `json:"name"` - // IsAutomated indicates whether the result is automated - IsAutomated bool `json:"is_automated"` - // Description is a textual description of the repository - Description string `json:"description"` -} - -// SearchResults lists a collection search results returned from a registry -type SearchResults struct { - // Query contains the query string that generated the search results - Query string `json:"query"` - // NumResults indicates the number of results the query returned - NumResults int `json:"num_results"` - // Results is a slice containing the actual results for the search - Results []SearchResult `json:"results"` -} - -// DistributionInspect describes the result obtained from contacting the -// registry to retrieve image metadata -type DistributionInspect struct { - // Descriptor contains information about the manifest, including - // the content addressable digest - Descriptor v1.Descriptor - // Platforms contains the list of platforms supported by the image, - // obtained by parsing the manifest - Platforms []v1.Platform -} diff --git a/vendor/github.com/docker/docker/api/types/service_update_response.go b/vendor/github.com/docker/docker/api/types/service_update_response.go deleted file mode 100644 index 74ea64b1bb6..00000000000 --- a/vendor/github.com/docker/docker/api/types/service_update_response.go +++ /dev/null @@ -1,12 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// ServiceUpdateResponse service update response -// swagger:model ServiceUpdateResponse -type ServiceUpdateResponse struct { - - // Optional warning messages - Warnings []string `json:"Warnings"` -} diff --git a/vendor/github.com/docker/docker/api/types/stats.go b/vendor/github.com/docker/docker/api/types/stats.go deleted file mode 100644 index 20daebed14b..00000000000 --- a/vendor/github.com/docker/docker/api/types/stats.go +++ /dev/null @@ -1,181 +0,0 @@ -// Package types is used for API stability in the types and response to the -// consumers of the API stats endpoint. -package types // import "github.com/docker/docker/api/types" - -import "time" - -// ThrottlingData stores CPU throttling stats of one running container. -// Not used on Windows. -type ThrottlingData struct { - // Number of periods with throttling active - Periods uint64 `json:"periods"` - // Number of periods when the container hits its throttling limit. - ThrottledPeriods uint64 `json:"throttled_periods"` - // Aggregate time the container was throttled for in nanoseconds. - ThrottledTime uint64 `json:"throttled_time"` -} - -// CPUUsage stores All CPU stats aggregated since container inception. -type CPUUsage struct { - // Total CPU time consumed. - // Units: nanoseconds (Linux) - // Units: 100's of nanoseconds (Windows) - TotalUsage uint64 `json:"total_usage"` - - // Total CPU time consumed per core (Linux). Not used on Windows. - // Units: nanoseconds. - PercpuUsage []uint64 `json:"percpu_usage,omitempty"` - - // Time spent by tasks of the cgroup in kernel mode (Linux). - // Time spent by all container processes in kernel mode (Windows). - // Units: nanoseconds (Linux). - // Units: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers. - UsageInKernelmode uint64 `json:"usage_in_kernelmode"` - - // Time spent by tasks of the cgroup in user mode (Linux). - // Time spent by all container processes in user mode (Windows). - // Units: nanoseconds (Linux). - // Units: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers - UsageInUsermode uint64 `json:"usage_in_usermode"` -} - -// CPUStats aggregates and wraps all CPU related info of container -type CPUStats struct { - // CPU Usage. Linux and Windows. - CPUUsage CPUUsage `json:"cpu_usage"` - - // System Usage. Linux only. - SystemUsage uint64 `json:"system_cpu_usage,omitempty"` - - // Online CPUs. Linux only. - OnlineCPUs uint32 `json:"online_cpus,omitempty"` - - // Throttling Data. Linux only. - ThrottlingData ThrottlingData `json:"throttling_data,omitempty"` -} - -// MemoryStats aggregates all memory stats since container inception on Linux. -// Windows returns stats for commit and private working set only. -type MemoryStats struct { - // Linux Memory Stats - - // current res_counter usage for memory - Usage uint64 `json:"usage,omitempty"` - // maximum usage ever recorded. - MaxUsage uint64 `json:"max_usage,omitempty"` - // TODO(vishh): Export these as stronger types. - // all the stats exported via memory.stat. - Stats map[string]uint64 `json:"stats,omitempty"` - // number of times memory usage hits limits. - Failcnt uint64 `json:"failcnt,omitempty"` - Limit uint64 `json:"limit,omitempty"` - - // Windows Memory Stats - // See https://technet.microsoft.com/en-us/magazine/ff382715.aspx - - // committed bytes - Commit uint64 `json:"commitbytes,omitempty"` - // peak committed bytes - CommitPeak uint64 `json:"commitpeakbytes,omitempty"` - // private working set - PrivateWorkingSet uint64 `json:"privateworkingset,omitempty"` -} - -// BlkioStatEntry is one small entity to store a piece of Blkio stats -// Not used on Windows. -type BlkioStatEntry struct { - Major uint64 `json:"major"` - Minor uint64 `json:"minor"` - Op string `json:"op"` - Value uint64 `json:"value"` -} - -// 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. -type BlkioStats struct { - // number of bytes transferred to and from the block device - IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"` - IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive"` - IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive"` - IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive"` - IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive"` - IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive"` - IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive"` - SectorsRecursive []BlkioStatEntry `json:"sectors_recursive"` -} - -// StorageStats is the disk I/O stats for read/write on Windows. -type StorageStats struct { - ReadCountNormalized uint64 `json:"read_count_normalized,omitempty"` - ReadSizeBytes uint64 `json:"read_size_bytes,omitempty"` - WriteCountNormalized uint64 `json:"write_count_normalized,omitempty"` - WriteSizeBytes uint64 `json:"write_size_bytes,omitempty"` -} - -// NetworkStats aggregates the network stats of one container -type NetworkStats struct { - // Bytes received. Windows and Linux. - RxBytes uint64 `json:"rx_bytes"` - // Packets received. Windows and Linux. - RxPackets uint64 `json:"rx_packets"` - // Received errors. Not used on Windows. Note that we don't `omitempty` this - // field as it is expected in the >=v1.21 API stats structure. - RxErrors uint64 `json:"rx_errors"` - // Incoming packets dropped. Windows and Linux. - RxDropped uint64 `json:"rx_dropped"` - // Bytes sent. Windows and Linux. - TxBytes uint64 `json:"tx_bytes"` - // Packets sent. Windows and Linux. - TxPackets uint64 `json:"tx_packets"` - // Sent errors. Not used on Windows. Note that we don't `omitempty` this - // field as it is expected in the >=v1.21 API stats structure. - TxErrors uint64 `json:"tx_errors"` - // Outgoing packets dropped. Windows and Linux. - TxDropped uint64 `json:"tx_dropped"` - // Endpoint ID. Not used on Linux. - EndpointID string `json:"endpoint_id,omitempty"` - // Instance ID. Not used on Linux. - InstanceID string `json:"instance_id,omitempty"` -} - -// PidsStats contains the stats of a container's pids -type PidsStats struct { - // Current is the number of pids in the cgroup - Current uint64 `json:"current,omitempty"` - // Limit is the hard limit on the number of pids in the cgroup. - // A "Limit" of 0 means that there is no limit. - Limit uint64 `json:"limit,omitempty"` -} - -// Stats is Ultimate struct aggregating all types of stats of one container -type Stats struct { - // Common stats - Read time.Time `json:"read"` - PreRead time.Time `json:"preread"` - - // Linux specific stats, not populated on Windows. - PidsStats PidsStats `json:"pids_stats,omitempty"` - BlkioStats BlkioStats `json:"blkio_stats,omitempty"` - - // Windows specific stats, not populated on Linux. - NumProcs uint32 `json:"num_procs"` - 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"` -} - -// StatsJSON is newly used Networks -type StatsJSON struct { - Stats - - Name string `json:"name,omitempty"` - ID string `json:"id,omitempty"` - - // Networks request version >=1.21 - Networks map[string]NetworkStats `json:"networks,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/strslice/strslice.go b/vendor/github.com/docker/docker/api/types/strslice/strslice.go deleted file mode 100644 index 82921cebc15..00000000000 --- a/vendor/github.com/docker/docker/api/types/strslice/strslice.go +++ /dev/null @@ -1,30 +0,0 @@ -package strslice // import "github.com/docker/docker/api/types/strslice" - -import "encoding/json" - -// StrSlice represents a string or an array of strings. -// We need to override the json decoder to accept both options. -type StrSlice []string - -// UnmarshalJSON decodes the byte slice whether it's a string or an array of -// strings. This method is needed to implement json.Unmarshaler. -func (e *StrSlice) UnmarshalJSON(b []byte) error { - if len(b) == 0 { - // With no input, we preserve the existing value by returning nil and - // leaving the target alone. This allows defining default values for - // the type. - return nil - } - - p := make([]string, 0, 1) - if err := json.Unmarshal(b, &p); err != nil { - var s string - if err := json.Unmarshal(b, &s); err != nil { - return err - } - p = append(p, s) - } - - *e = p - return nil -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/common.go b/vendor/github.com/docker/docker/api/types/swarm/common.go deleted file mode 100644 index ef020f458bd..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/common.go +++ /dev/null @@ -1,40 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "time" - -// Version represents the internal object version. -type Version struct { - Index uint64 `json:",omitempty"` -} - -// Meta is a base object inherited by most of the other once. -type Meta struct { - Version Version `json:",omitempty"` - CreatedAt time.Time `json:",omitempty"` - UpdatedAt time.Time `json:",omitempty"` -} - -// Annotations represents how to describe an object. -type Annotations struct { - Name string `json:",omitempty"` - Labels map[string]string `json:"Labels"` -} - -// Driver represents a driver (network, logging, secrets backend). -type Driver struct { - Name string `json:",omitempty"` - Options map[string]string `json:",omitempty"` -} - -// TLSInfo represents the TLS information about what CA certificate is trusted, -// and who the issuer for a TLS certificate is -type TLSInfo struct { - // TrustRoot is the trusted CA root certificate in PEM format - TrustRoot string `json:",omitempty"` - - // CertIssuer is the raw subject bytes of the issuer - CertIssuerSubject []byte `json:",omitempty"` - - // CertIssuerPublicKey is the raw public key bytes of the issuer - CertIssuerPublicKey []byte `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/config.go b/vendor/github.com/docker/docker/api/types/swarm/config.go deleted file mode 100644 index 16202ccce61..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/config.go +++ /dev/null @@ -1,40 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "os" - -// Config represents a config. -type Config struct { - ID string - Meta - Spec ConfigSpec -} - -// ConfigSpec represents a config specification from a config in swarm -type ConfigSpec struct { - Annotations - Data []byte `json:",omitempty"` - - // Templating controls whether and how to evaluate the config payload as - // a template. If it is not set, no templating is used. - Templating *Driver `json:",omitempty"` -} - -// ConfigReferenceFileTarget is a file target in a config reference -type ConfigReferenceFileTarget struct { - Name string - UID string - GID string - Mode os.FileMode -} - -// ConfigReferenceRuntimeTarget is a target for a config specifying that it -// isn't mounted into the container but instead has some other purpose. -type ConfigReferenceRuntimeTarget struct{} - -// ConfigReference is a reference to a config in swarm -type ConfigReference struct { - File *ConfigReferenceFileTarget `json:",omitempty"` - Runtime *ConfigReferenceRuntimeTarget `json:",omitempty"` - ConfigID string - ConfigName string -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/container.go b/vendor/github.com/docker/docker/api/types/swarm/container.go deleted file mode 100644 index af5e1c0bc27..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/container.go +++ /dev/null @@ -1,80 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import ( - "time" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/mount" - "github.com/docker/go-units" -) - -// DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf) -// Detailed documentation is available in: -// http://man7.org/linux/man-pages/man5/resolv.conf.5.html -// `nameserver`, `search`, `options` have been supported. -// TODO: `domain` is not supported yet. -type DNSConfig struct { - // Nameservers specifies the IP addresses of the name servers - Nameservers []string `json:",omitempty"` - // Search specifies the search list for host-name lookup - Search []string `json:",omitempty"` - // Options allows certain internal resolver variables to be modified - Options []string `json:",omitempty"` -} - -// SELinuxContext contains the SELinux labels of the container. -type SELinuxContext struct { - Disable bool - - User string - Role string - Type string - Level string -} - -// CredentialSpec for managed service account (Windows only) -type CredentialSpec struct { - Config string - File string - Registry string -} - -// Privileges defines the security options for the container. -type Privileges struct { - CredentialSpec *CredentialSpec - SELinuxContext *SELinuxContext -} - -// ContainerSpec represents the spec of a container. -type ContainerSpec struct { - Image string `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - Command []string `json:",omitempty"` - Args []string `json:",omitempty"` - Hostname string `json:",omitempty"` - Env []string `json:",omitempty"` - Dir string `json:",omitempty"` - User string `json:",omitempty"` - Groups []string `json:",omitempty"` - Privileges *Privileges `json:",omitempty"` - Init *bool `json:",omitempty"` - StopSignal string `json:",omitempty"` - TTY bool `json:",omitempty"` - OpenStdin bool `json:",omitempty"` - ReadOnly bool `json:",omitempty"` - Mounts []mount.Mount `json:",omitempty"` - StopGracePeriod *time.Duration `json:",omitempty"` - Healthcheck *container.HealthConfig `json:",omitempty"` - // The format of extra hosts on swarmkit is specified in: - // http://man7.org/linux/man-pages/man5/hosts.5.html - // IP_address canonical_hostname [aliases...] - Hosts []string `json:",omitempty"` - DNSConfig *DNSConfig `json:",omitempty"` - Secrets []*SecretReference `json:",omitempty"` - Configs []*ConfigReference `json:",omitempty"` - Isolation container.Isolation `json:",omitempty"` - Sysctls map[string]string `json:",omitempty"` - CapabilityAdd []string `json:",omitempty"` - CapabilityDrop []string `json:",omitempty"` - Ulimits []*units.Ulimit `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/network.go b/vendor/github.com/docker/docker/api/types/swarm/network.go deleted file mode 100644 index 98ef3284d1d..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/network.go +++ /dev/null @@ -1,121 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import ( - "github.com/docker/docker/api/types/network" -) - -// Endpoint represents an endpoint. -type Endpoint struct { - Spec EndpointSpec `json:",omitempty"` - Ports []PortConfig `json:",omitempty"` - VirtualIPs []EndpointVirtualIP `json:",omitempty"` -} - -// EndpointSpec represents the spec of an endpoint. -type EndpointSpec struct { - Mode ResolutionMode `json:",omitempty"` - Ports []PortConfig `json:",omitempty"` -} - -// ResolutionMode represents a resolution mode. -type ResolutionMode string - -const ( - // ResolutionModeVIP VIP - ResolutionModeVIP ResolutionMode = "vip" - // ResolutionModeDNSRR DNSRR - ResolutionModeDNSRR ResolutionMode = "dnsrr" -) - -// PortConfig represents the config of a port. -type PortConfig struct { - Name string `json:",omitempty"` - Protocol PortConfigProtocol `json:",omitempty"` - // TargetPort is the port inside the container - TargetPort uint32 `json:",omitempty"` - // PublishedPort is the port on the swarm hosts - PublishedPort uint32 `json:",omitempty"` - // PublishMode is the mode in which port is published - PublishMode PortConfigPublishMode `json:",omitempty"` -} - -// PortConfigPublishMode represents the mode in which the port is to -// be published. -type PortConfigPublishMode string - -const ( - // PortConfigPublishModeIngress is used for ports published - // for ingress load balancing using routing mesh. - PortConfigPublishModeIngress PortConfigPublishMode = "ingress" - // PortConfigPublishModeHost is used for ports published - // for direct host level access on the host where the task is running. - PortConfigPublishModeHost PortConfigPublishMode = "host" -) - -// PortConfigProtocol represents the protocol of a port. -type PortConfigProtocol string - -const ( - // TODO(stevvooe): These should be used generally, not just for PortConfig. - - // PortConfigProtocolTCP TCP - PortConfigProtocolTCP PortConfigProtocol = "tcp" - // PortConfigProtocolUDP UDP - PortConfigProtocolUDP PortConfigProtocol = "udp" - // PortConfigProtocolSCTP SCTP - PortConfigProtocolSCTP PortConfigProtocol = "sctp" -) - -// EndpointVirtualIP represents the virtual ip of a port. -type EndpointVirtualIP struct { - NetworkID string `json:",omitempty"` - Addr string `json:",omitempty"` -} - -// Network represents a network. -type Network struct { - ID string - Meta - Spec NetworkSpec `json:",omitempty"` - DriverState Driver `json:",omitempty"` - IPAMOptions *IPAMOptions `json:",omitempty"` -} - -// NetworkSpec represents the spec of a network. -type NetworkSpec struct { - Annotations - DriverConfiguration *Driver `json:",omitempty"` - IPv6Enabled bool `json:",omitempty"` - Internal bool `json:",omitempty"` - Attachable bool `json:",omitempty"` - Ingress bool `json:",omitempty"` - IPAMOptions *IPAMOptions `json:",omitempty"` - ConfigFrom *network.ConfigReference `json:",omitempty"` - Scope string `json:",omitempty"` -} - -// NetworkAttachmentConfig represents the configuration of a network attachment. -type NetworkAttachmentConfig struct { - Target string `json:",omitempty"` - Aliases []string `json:",omitempty"` - DriverOpts map[string]string `json:",omitempty"` -} - -// NetworkAttachment represents a network attachment. -type NetworkAttachment struct { - Network Network `json:",omitempty"` - Addresses []string `json:",omitempty"` -} - -// IPAMOptions represents ipam options. -type IPAMOptions struct { - Driver Driver `json:",omitempty"` - Configs []IPAMConfig `json:",omitempty"` -} - -// IPAMConfig represents ipam configuration. -type IPAMConfig struct { - Subnet string `json:",omitempty"` - Range string `json:",omitempty"` - Gateway string `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/node.go b/vendor/github.com/docker/docker/api/types/swarm/node.go deleted file mode 100644 index 1e30f5fa10d..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/node.go +++ /dev/null @@ -1,115 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -// Node represents a node. -type Node struct { - ID string - Meta - // Spec defines the desired state of the node as specified by the user. - // The system will honor this and will *never* modify it. - Spec NodeSpec `json:",omitempty"` - // Description encapsulates the properties of the Node as reported by the - // agent. - Description NodeDescription `json:",omitempty"` - // Status provides the current status of the node, as seen by the manager. - Status NodeStatus `json:",omitempty"` - // ManagerStatus provides the current status of the node's manager - // component, if the node is a manager. - ManagerStatus *ManagerStatus `json:",omitempty"` -} - -// NodeSpec represents the spec of a node. -type NodeSpec struct { - Annotations - Role NodeRole `json:",omitempty"` - Availability NodeAvailability `json:",omitempty"` -} - -// NodeRole represents the role of a node. -type NodeRole string - -const ( - // NodeRoleWorker WORKER - NodeRoleWorker NodeRole = "worker" - // NodeRoleManager MANAGER - NodeRoleManager NodeRole = "manager" -) - -// NodeAvailability represents the availability of a node. -type NodeAvailability string - -const ( - // NodeAvailabilityActive ACTIVE - NodeAvailabilityActive NodeAvailability = "active" - // NodeAvailabilityPause PAUSE - NodeAvailabilityPause NodeAvailability = "pause" - // NodeAvailabilityDrain DRAIN - NodeAvailabilityDrain NodeAvailability = "drain" -) - -// NodeDescription represents the description of a node. -type NodeDescription struct { - Hostname string `json:",omitempty"` - Platform Platform `json:",omitempty"` - Resources Resources `json:",omitempty"` - Engine EngineDescription `json:",omitempty"` - TLSInfo TLSInfo `json:",omitempty"` -} - -// Platform represents the platform (Arch/OS). -type Platform struct { - Architecture string `json:",omitempty"` - OS string `json:",omitempty"` -} - -// EngineDescription represents the description of an engine. -type EngineDescription struct { - EngineVersion string `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - Plugins []PluginDescription `json:",omitempty"` -} - -// PluginDescription represents the description of an engine plugin. -type PluginDescription struct { - Type string `json:",omitempty"` - Name string `json:",omitempty"` -} - -// NodeStatus represents the status of a node. -type NodeStatus struct { - State NodeState `json:",omitempty"` - Message string `json:",omitempty"` - Addr string `json:",omitempty"` -} - -// Reachability represents the reachability of a node. -type Reachability string - -const ( - // ReachabilityUnknown UNKNOWN - ReachabilityUnknown Reachability = "unknown" - // ReachabilityUnreachable UNREACHABLE - ReachabilityUnreachable Reachability = "unreachable" - // ReachabilityReachable REACHABLE - ReachabilityReachable Reachability = "reachable" -) - -// ManagerStatus represents the status of a manager. -type ManagerStatus struct { - Leader bool `json:",omitempty"` - Reachability Reachability `json:",omitempty"` - Addr string `json:",omitempty"` -} - -// NodeState represents the state of a node. -type NodeState string - -const ( - // NodeStateUnknown UNKNOWN - NodeStateUnknown NodeState = "unknown" - // NodeStateDown DOWN - NodeStateDown NodeState = "down" - // NodeStateReady READY - NodeStateReady NodeState = "ready" - // NodeStateDisconnected DISCONNECTED - NodeStateDisconnected NodeState = "disconnected" -) diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime.go b/vendor/github.com/docker/docker/api/types/swarm/runtime.go deleted file mode 100644 index 0c77403ccff..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime.go +++ /dev/null @@ -1,27 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -// RuntimeType is the type of runtime used for the TaskSpec -type RuntimeType string - -// RuntimeURL is the proto type url -type RuntimeURL string - -const ( - // RuntimeContainer is the container based runtime - RuntimeContainer RuntimeType = "container" - // RuntimePlugin is the plugin based runtime - RuntimePlugin RuntimeType = "plugin" - // RuntimeNetworkAttachment is the network attachment runtime - RuntimeNetworkAttachment RuntimeType = "attachment" - - // RuntimeURLContainer is the proto url for the container type - RuntimeURLContainer RuntimeURL = "types.docker.com/RuntimeContainer" - // RuntimeURLPlugin is the proto url for the plugin type - RuntimeURLPlugin RuntimeURL = "types.docker.com/RuntimePlugin" -) - -// NetworkAttachmentSpec represents the runtime spec type for network -// attachment tasks -type NetworkAttachmentSpec struct { - ContainerID string -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go b/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go deleted file mode 100644 index 98c2806c31d..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go +++ /dev/null @@ -1,3 +0,0 @@ -//go:generate protoc -I . --gogofast_out=import_path=github.com/docker/docker/api/types/swarm/runtime:. plugin.proto - -package runtime // import "github.com/docker/docker/api/types/swarm/runtime" diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go b/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go deleted file mode 100644 index e45045866a6..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go +++ /dev/null @@ -1,754 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: plugin.proto - -/* - Package runtime is a generated protocol buffer package. - - It is generated from these files: - plugin.proto - - It has these top-level messages: - PluginSpec - PluginPrivilege -*/ -package runtime - -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -import io "io" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package - -// PluginSpec defines the base payload which clients can specify for creating -// a service with the plugin runtime. -type PluginSpec struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Remote string `protobuf:"bytes,2,opt,name=remote,proto3" json:"remote,omitempty"` - Privileges []*PluginPrivilege `protobuf:"bytes,3,rep,name=privileges" json:"privileges,omitempty"` - Disabled bool `protobuf:"varint,4,opt,name=disabled,proto3" json:"disabled,omitempty"` - Env []string `protobuf:"bytes,5,rep,name=env" json:"env,omitempty"` -} - -func (m *PluginSpec) Reset() { *m = PluginSpec{} } -func (m *PluginSpec) String() string { return proto.CompactTextString(m) } -func (*PluginSpec) ProtoMessage() {} -func (*PluginSpec) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{0} } - -func (m *PluginSpec) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *PluginSpec) GetRemote() string { - if m != nil { - return m.Remote - } - return "" -} - -func (m *PluginSpec) GetPrivileges() []*PluginPrivilege { - if m != nil { - return m.Privileges - } - return nil -} - -func (m *PluginSpec) GetDisabled() bool { - if m != nil { - return m.Disabled - } - return false -} - -func (m *PluginSpec) GetEnv() []string { - if m != nil { - return m.Env - } - return nil -} - -// PluginPrivilege describes a permission the user has to accept -// upon installing a plugin. -type PluginPrivilege struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - Value []string `protobuf:"bytes,3,rep,name=value" json:"value,omitempty"` -} - -func (m *PluginPrivilege) Reset() { *m = PluginPrivilege{} } -func (m *PluginPrivilege) String() string { return proto.CompactTextString(m) } -func (*PluginPrivilege) ProtoMessage() {} -func (*PluginPrivilege) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{1} } - -func (m *PluginPrivilege) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *PluginPrivilege) GetDescription() string { - if m != nil { - return m.Description - } - return "" -} - -func (m *PluginPrivilege) GetValue() []string { - if m != nil { - return m.Value - } - return nil -} - -func init() { - proto.RegisterType((*PluginSpec)(nil), "PluginSpec") - proto.RegisterType((*PluginPrivilege)(nil), "PluginPrivilege") -} -func (m *PluginSpec) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PluginSpec) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Name) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name))) - i += copy(dAtA[i:], m.Name) - } - if len(m.Remote) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintPlugin(dAtA, i, uint64(len(m.Remote))) - i += copy(dAtA[i:], m.Remote) - } - if len(m.Privileges) > 0 { - for _, msg := range m.Privileges { - dAtA[i] = 0x1a - i++ - i = encodeVarintPlugin(dAtA, i, uint64(msg.Size())) - n, err := msg.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n - } - } - if m.Disabled { - dAtA[i] = 0x20 - i++ - if m.Disabled { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i++ - } - if len(m.Env) > 0 { - for _, s := range m.Env { - dAtA[i] = 0x2a - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) - } - } - return i, nil -} - -func (m *PluginPrivilege) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PluginPrivilege) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Name) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name))) - i += copy(dAtA[i:], m.Name) - } - if len(m.Description) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintPlugin(dAtA, i, uint64(len(m.Description))) - i += copy(dAtA[i:], m.Description) - } - if len(m.Value) > 0 { - for _, s := range m.Value { - dAtA[i] = 0x1a - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) - } - } - return i, nil -} - -func encodeVarintPlugin(dAtA []byte, offset int, v uint64) int { - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return offset + 1 -} -func (m *PluginSpec) Size() (n int) { - var l int - _ = l - l = len(m.Name) - if l > 0 { - n += 1 + l + sovPlugin(uint64(l)) - } - l = len(m.Remote) - if l > 0 { - n += 1 + l + sovPlugin(uint64(l)) - } - if len(m.Privileges) > 0 { - for _, e := range m.Privileges { - l = e.Size() - n += 1 + l + sovPlugin(uint64(l)) - } - } - if m.Disabled { - n += 2 - } - if len(m.Env) > 0 { - for _, s := range m.Env { - l = len(s) - n += 1 + l + sovPlugin(uint64(l)) - } - } - return n -} - -func (m *PluginPrivilege) Size() (n int) { - var l int - _ = l - l = len(m.Name) - if l > 0 { - n += 1 + l + sovPlugin(uint64(l)) - } - l = len(m.Description) - if l > 0 { - n += 1 + l + sovPlugin(uint64(l)) - } - if len(m.Value) > 0 { - for _, s := range m.Value { - l = len(s) - n += 1 + l + sovPlugin(uint64(l)) - } - } - return n -} - -func sovPlugin(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} -func sozPlugin(x uint64) (n int) { - return sovPlugin(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *PluginSpec) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PluginSpec: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PluginSpec: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Remote", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Remote = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Privileges", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Privileges = append(m.Privileges, &PluginPrivilege{}) - if err := m.Privileges[len(m.Privileges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Disabled", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - m.Disabled = bool(v != 0) - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Env", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Env = append(m.Env, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipPlugin(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthPlugin - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PluginPrivilege) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PluginPrivilege: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PluginPrivilege: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Description = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlugin - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPlugin - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Value = append(m.Value, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipPlugin(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthPlugin - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipPlugin(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowPlugin - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowPlugin - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowPlugin - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - iNdEx += length - if length < 0 { - return 0, ErrInvalidLengthPlugin - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowPlugin - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipPlugin(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") -} - -var ( - ErrInvalidLengthPlugin = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowPlugin = fmt.Errorf("proto: integer overflow") -) - -func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) } - -var fileDescriptorPlugin = []byte{ - // 256 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x4d, 0x4b, 0xc3, 0x30, - 0x18, 0xc7, 0x89, 0xdd, 0xc6, 0xfa, 0x4c, 0x70, 0x04, 0x91, 0xe2, 0xa1, 0x94, 0x9d, 0x7a, 0x6a, - 0x45, 0x2f, 0x82, 0x37, 0x0f, 0x9e, 0x47, 0xbc, 0x09, 0x1e, 0xd2, 0xf6, 0xa1, 0x06, 0x9b, 0x17, - 0x92, 0xb4, 0xe2, 0x37, 0xf1, 0x23, 0x79, 0xf4, 0x23, 0x48, 0x3f, 0x89, 0x98, 0x75, 0x32, 0x64, - 0xa7, 0xff, 0x4b, 0xc2, 0x9f, 0x1f, 0x0f, 0x9c, 0x9a, 0xae, 0x6f, 0x85, 0x2a, 0x8c, 0xd5, 0x5e, - 0x6f, 0x3e, 0x08, 0xc0, 0x36, 0x14, 0x8f, 0x06, 0x6b, 0x4a, 0x61, 0xa6, 0xb8, 0xc4, 0x84, 0x64, - 0x24, 0x8f, 0x59, 0xf0, 0xf4, 0x02, 0x16, 0x16, 0xa5, 0xf6, 0x98, 0x9c, 0x84, 0x76, 0x4a, 0xf4, - 0x0a, 0xc0, 0x58, 0x31, 0x88, 0x0e, 0x5b, 0x74, 0x49, 0x94, 0x45, 0xf9, 0xea, 0x7a, 0x5d, 0xec, - 0xc6, 0xb6, 0xfb, 0x07, 0x76, 0xf0, 0x87, 0x5e, 0xc2, 0xb2, 0x11, 0x8e, 0x57, 0x1d, 0x36, 0xc9, - 0x2c, 0x23, 0xf9, 0x92, 0xfd, 0x65, 0xba, 0x86, 0x08, 0xd5, 0x90, 0xcc, 0xb3, 0x28, 0x8f, 0xd9, - 0xaf, 0xdd, 0x3c, 0xc3, 0xd9, 0xbf, 0xb1, 0xa3, 0x78, 0x19, 0xac, 0x1a, 0x74, 0xb5, 0x15, 0xc6, - 0x0b, 0xad, 0x26, 0xc6, 0xc3, 0x8a, 0x9e, 0xc3, 0x7c, 0xe0, 0x5d, 0x8f, 0x81, 0x31, 0x66, 0xbb, - 0x70, 0xff, 0xf0, 0x39, 0xa6, 0xe4, 0x6b, 0x4c, 0xc9, 0xf7, 0x98, 0x92, 0xa7, 0xdb, 0x56, 0xf8, - 0x97, 0xbe, 0x2a, 0x6a, 0x2d, 0xcb, 0x46, 0xd7, 0xaf, 0x68, 0xf7, 0xc2, 0x8d, 0x28, 0xfd, 0xbb, - 0x41, 0x57, 0xba, 0x37, 0x6e, 0x65, 0x69, 0x7b, 0xe5, 0x85, 0xc4, 0xbb, 0x49, 0xab, 0x45, 0x38, - 0xe4, 0xcd, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x99, 0xa8, 0xd9, 0x9b, 0x58, 0x01, 0x00, 0x00, -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto b/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto deleted file mode 100644 index 9ef169046b4..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto +++ /dev/null @@ -1,21 +0,0 @@ -syntax = "proto3"; - -option go_package = "github.com/docker/docker/api/types/swarm/runtime;runtime"; - -// PluginSpec defines the base payload which clients can specify for creating -// a service with the plugin runtime. -message PluginSpec { - string name = 1; - string remote = 2; - repeated PluginPrivilege privileges = 3; - bool disabled = 4; - repeated string env = 5; -} - -// PluginPrivilege describes a permission the user has to accept -// upon installing a plugin. -message PluginPrivilege { - string name = 1; - string description = 2; - repeated string value = 3; -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/secret.go b/vendor/github.com/docker/docker/api/types/swarm/secret.go deleted file mode 100644 index d5213ec981c..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/secret.go +++ /dev/null @@ -1,36 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "os" - -// Secret represents a secret. -type Secret struct { - ID string - Meta - Spec SecretSpec -} - -// SecretSpec represents a secret specification from a secret in swarm -type SecretSpec struct { - Annotations - Data []byte `json:",omitempty"` - Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store - - // Templating controls whether and how to evaluate the secret payload as - // a template. If it is not set, no templating is used. - Templating *Driver `json:",omitempty"` -} - -// SecretReferenceFileTarget is a file target in a secret reference -type SecretReferenceFileTarget struct { - Name string - UID string - GID string - Mode os.FileMode -} - -// SecretReference is a reference to a secret in swarm -type SecretReference struct { - File *SecretReferenceFileTarget - SecretID string - SecretName string -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/service.go b/vendor/github.com/docker/docker/api/types/swarm/service.go deleted file mode 100644 index 6eb452d24d1..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/service.go +++ /dev/null @@ -1,202 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import "time" - -// Service represents a service. -type Service struct { - ID string - Meta - Spec ServiceSpec `json:",omitempty"` - PreviousSpec *ServiceSpec `json:",omitempty"` - Endpoint Endpoint `json:",omitempty"` - UpdateStatus *UpdateStatus `json:",omitempty"` - - // ServiceStatus is an optional, extra field indicating the number of - // desired and running tasks. It is provided primarily as a shortcut to - // calculating these values client-side, which otherwise would require - // listing all tasks for a service, an operation that could be - // computation and network expensive. - ServiceStatus *ServiceStatus `json:",omitempty"` - - // JobStatus is the status of a Service which is in one of ReplicatedJob or - // GlobalJob modes. It is absent on Replicated and Global services. - JobStatus *JobStatus `json:",omitempty"` -} - -// ServiceSpec represents the spec of a service. -type ServiceSpec struct { - Annotations - - // TaskTemplate defines how the service should construct new tasks when - // orchestrating this service. - TaskTemplate TaskSpec `json:",omitempty"` - Mode ServiceMode `json:",omitempty"` - UpdateConfig *UpdateConfig `json:",omitempty"` - RollbackConfig *UpdateConfig `json:",omitempty"` - - // Networks field in ServiceSpec is deprecated. The - // same field in TaskSpec should be used instead. - // This field will be removed in a future release. - Networks []NetworkAttachmentConfig `json:",omitempty"` - EndpointSpec *EndpointSpec `json:",omitempty"` -} - -// ServiceMode represents the mode of a service. -type ServiceMode struct { - Replicated *ReplicatedService `json:",omitempty"` - Global *GlobalService `json:",omitempty"` - ReplicatedJob *ReplicatedJob `json:",omitempty"` - GlobalJob *GlobalJob `json:",omitempty"` -} - -// UpdateState is the state of a service update. -type UpdateState string - -const ( - // UpdateStateUpdating is the updating state. - UpdateStateUpdating UpdateState = "updating" - // UpdateStatePaused is the paused state. - UpdateStatePaused UpdateState = "paused" - // UpdateStateCompleted is the completed state. - UpdateStateCompleted UpdateState = "completed" - // UpdateStateRollbackStarted is the state with a rollback in progress. - UpdateStateRollbackStarted UpdateState = "rollback_started" - // UpdateStateRollbackPaused is the state with a rollback in progress. - UpdateStateRollbackPaused UpdateState = "rollback_paused" - // UpdateStateRollbackCompleted is the state with a rollback in progress. - UpdateStateRollbackCompleted UpdateState = "rollback_completed" -) - -// UpdateStatus reports the status of a service update. -type UpdateStatus struct { - State UpdateState `json:",omitempty"` - StartedAt *time.Time `json:",omitempty"` - CompletedAt *time.Time `json:",omitempty"` - Message string `json:",omitempty"` -} - -// ReplicatedService is a kind of ServiceMode. -type ReplicatedService struct { - Replicas *uint64 `json:",omitempty"` -} - -// GlobalService is a kind of ServiceMode. -type GlobalService struct{} - -// ReplicatedJob is the a type of Service which executes a defined Tasks -// in parallel until the specified number of Tasks have succeeded. -type ReplicatedJob struct { - // MaxConcurrent indicates the maximum number of Tasks that should be - // executing simultaneously for this job at any given time. There may be - // fewer Tasks that MaxConcurrent executing simultaneously; for example, if - // there are fewer than MaxConcurrent tasks needed to reach - // TotalCompletions. - // - // If this field is empty, it will default to a max concurrency of 1. - MaxConcurrent *uint64 `json:",omitempty"` - - // TotalCompletions is the total number of Tasks desired to run to - // completion. - // - // If this field is empty, the value of MaxConcurrent will be used. - TotalCompletions *uint64 `json:",omitempty"` -} - -// GlobalJob is the type of a Service which executes a Task on every Node -// matching the Service's placement constraints. These tasks run to completion -// and then exit. -// -// This type is deliberately empty. -type GlobalJob struct{} - -const ( - // UpdateFailureActionPause PAUSE - UpdateFailureActionPause = "pause" - // UpdateFailureActionContinue CONTINUE - UpdateFailureActionContinue = "continue" - // UpdateFailureActionRollback ROLLBACK - UpdateFailureActionRollback = "rollback" - - // UpdateOrderStopFirst STOP_FIRST - UpdateOrderStopFirst = "stop-first" - // UpdateOrderStartFirst START_FIRST - UpdateOrderStartFirst = "start-first" -) - -// UpdateConfig represents the update configuration. -type UpdateConfig struct { - // Maximum number of tasks to be updated in one iteration. - // 0 means unlimited parallelism. - Parallelism uint64 - - // Amount of time between updates. - Delay time.Duration `json:",omitempty"` - - // FailureAction is the action to take when an update failures. - FailureAction string `json:",omitempty"` - - // Monitor indicates how long to monitor a task for failure after it is - // created. If the task fails by ending up in one of the states - // REJECTED, COMPLETED, or FAILED, within Monitor from its creation, - // this counts as a failure. If it fails after Monitor, it does not - // count as a failure. If Monitor is unspecified, a default value will - // be used. - Monitor time.Duration `json:",omitempty"` - - // MaxFailureRatio is the fraction of tasks that may fail during - // an update before the failure action is invoked. Any task created by - // the current update which ends up in one of the states REJECTED, - // COMPLETED or FAILED within Monitor from its creation counts as a - // failure. The number of failures is divided by the number of tasks - // being updated, and if this fraction is greater than - // MaxFailureRatio, the failure action is invoked. - // - // If the failure action is CONTINUE, there is no effect. - // If the failure action is PAUSE, no more tasks will be updated until - // another update is started. - MaxFailureRatio float32 - - // Order indicates the order of operations when rolling out an updated - // task. Either the old task is shut down before the new task is - // started, or the new task is started before the old task is shut down. - Order string -} - -// ServiceStatus represents the number of running tasks in a service and the -// number of tasks desired to be running. -type ServiceStatus struct { - // RunningTasks is the number of tasks for the service actually in the - // Running state - RunningTasks uint64 - - // DesiredTasks is the number of tasks desired to be running by the - // service. For replicated services, this is the replica count. For global - // services, this is computed by taking the number of tasks with desired - // state of not-Shutdown. - DesiredTasks uint64 - - // CompletedTasks is the number of tasks in the state Completed, if this - // service is in ReplicatedJob or GlobalJob mode. This field must be - // cross-referenced with the service type, because the default value of 0 - // may mean that a service is not in a job mode, or it may mean that the - // job has yet to complete any tasks. - CompletedTasks uint64 -} - -// JobStatus is the status of a job-type service. -type JobStatus struct { - // JobIteration is a value increased each time a Job is executed, - // successfully or otherwise. "Executed", in this case, means the job as a - // whole has been started, not that an individual Task has been launched. A - // job is "Executed" when its ServiceSpec is updated. JobIteration can be - // used to disambiguate Tasks belonging to different executions of a job. - // - // Though JobIteration will increase with each subsequent execution, it may - // not necessarily increase by 1, and so JobIteration should not be used to - // keep track of the number of times a job has been executed. - JobIteration Version - - // LastExecution is the time that the job was last executed, as observed by - // Swarm manager. - LastExecution time.Time `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/swarm.go b/vendor/github.com/docker/docker/api/types/swarm/swarm.go deleted file mode 100644 index b25f9996462..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/swarm.go +++ /dev/null @@ -1,227 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import ( - "time" -) - -// ClusterInfo represents info about the cluster for outputting in "info" -// it contains the same information as "Swarm", but without the JoinTokens -type ClusterInfo struct { - ID string - Meta - Spec Spec - TLSInfo TLSInfo - RootRotationInProgress bool - DefaultAddrPool []string - SubnetSize uint32 - DataPathPort uint32 -} - -// Swarm represents a swarm. -type Swarm struct { - ClusterInfo - JoinTokens JoinTokens -} - -// JoinTokens contains the tokens workers and managers need to join the swarm. -type JoinTokens struct { - // Worker is the join token workers may use to join the swarm. - Worker string - // Manager is the join token managers may use to join the swarm. - Manager string -} - -// Spec represents the spec of a swarm. -type Spec struct { - Annotations - - Orchestration OrchestrationConfig `json:",omitempty"` - Raft RaftConfig `json:",omitempty"` - Dispatcher DispatcherConfig `json:",omitempty"` - CAConfig CAConfig `json:",omitempty"` - TaskDefaults TaskDefaults `json:",omitempty"` - EncryptionConfig EncryptionConfig `json:",omitempty"` -} - -// OrchestrationConfig represents orchestration configuration. -type OrchestrationConfig struct { - // TaskHistoryRetentionLimit is the number of historic tasks to keep per instance or - // node. If negative, never remove completed or failed tasks. - TaskHistoryRetentionLimit *int64 `json:",omitempty"` -} - -// TaskDefaults parameterizes cluster-level task creation with default values. -type TaskDefaults struct { - // LogDriver selects the log driver to use for tasks created in the - // orchestrator if unspecified by a service. - // - // Updating this value will only have an affect on new tasks. Old tasks - // will continue use their previously configured log driver until - // recreated. - LogDriver *Driver `json:",omitempty"` -} - -// EncryptionConfig controls at-rest encryption of data and keys. -type EncryptionConfig struct { - // AutoLockManagers specifies whether or not managers TLS keys and raft data - // should be encrypted at rest in such a way that they must be unlocked - // before the manager node starts up again. - AutoLockManagers bool -} - -// RaftConfig represents raft configuration. -type RaftConfig struct { - // SnapshotInterval is the number of log entries between snapshots. - SnapshotInterval uint64 `json:",omitempty"` - - // KeepOldSnapshots is the number of snapshots to keep beyond the - // current snapshot. - KeepOldSnapshots *uint64 `json:",omitempty"` - - // LogEntriesForSlowFollowers is the number of log entries to keep - // around to sync up slow followers after a snapshot is created. - LogEntriesForSlowFollowers uint64 `json:",omitempty"` - - // ElectionTick is the number of ticks that a follower will wait for a message - // from the leader before becoming a candidate and starting an election. - // ElectionTick must be greater than HeartbeatTick. - // - // A tick currently defaults to one second, so these translate directly to - // seconds currently, but this is NOT guaranteed. - ElectionTick int - - // HeartbeatTick is the number of ticks between heartbeats. Every - // HeartbeatTick ticks, the leader will send a heartbeat to the - // followers. - // - // A tick currently defaults to one second, so these translate directly to - // seconds currently, but this is NOT guaranteed. - HeartbeatTick int -} - -// DispatcherConfig represents dispatcher configuration. -type DispatcherConfig struct { - // HeartbeatPeriod defines how often agent should send heartbeats to - // dispatcher. - HeartbeatPeriod time.Duration `json:",omitempty"` -} - -// CAConfig represents CA configuration. -type CAConfig struct { - // NodeCertExpiry is the duration certificates should be issued for - NodeCertExpiry time.Duration `json:",omitempty"` - - // ExternalCAs is a list of CAs to which a manager node will make - // certificate signing requests for node certificates. - ExternalCAs []*ExternalCA `json:",omitempty"` - - // SigningCACert and SigningCAKey specify the desired signing root CA and - // root CA key for the swarm. When inspecting the cluster, the key will - // be redacted. - SigningCACert string `json:",omitempty"` - 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. - ForceRotate uint64 `json:",omitempty"` -} - -// ExternalCAProtocol represents type of external CA. -type ExternalCAProtocol string - -// ExternalCAProtocolCFSSL CFSSL -const ExternalCAProtocolCFSSL ExternalCAProtocol = "cfssl" - -// ExternalCA defines external CA to be used by the cluster. -type ExternalCA struct { - // Protocol is the protocol used by this external CA. - Protocol ExternalCAProtocol - - // URL is the URL where the external CA can be reached. - URL string - - // Options is a set of additional key/value pairs whose interpretation - // depends on the specified CA type. - Options map[string]string `json:",omitempty"` - - // CACert specifies which root CA is used by this external CA. This certificate must - // be in PEM format. - CACert string -} - -// InitRequest is the request used to init a swarm. -type InitRequest struct { - ListenAddr string - AdvertiseAddr string - DataPathAddr string - DataPathPort uint32 - ForceNewCluster bool - Spec Spec - AutoLockManagers bool - Availability NodeAvailability - DefaultAddrPool []string - SubnetSize uint32 -} - -// JoinRequest is the request used to join a swarm. -type JoinRequest struct { - ListenAddr string - AdvertiseAddr string - DataPathAddr string - RemoteAddrs []string - JoinToken string // accept by secret - Availability NodeAvailability -} - -// UnlockRequest is the request used to unlock a swarm. -type UnlockRequest struct { - // UnlockKey is the unlock key in ASCII-armored format. - UnlockKey string -} - -// LocalNodeState represents the state of the local node. -type LocalNodeState string - -const ( - // LocalNodeStateInactive INACTIVE - LocalNodeStateInactive LocalNodeState = "inactive" - // LocalNodeStatePending PENDING - LocalNodeStatePending LocalNodeState = "pending" - // LocalNodeStateActive ACTIVE - LocalNodeStateActive LocalNodeState = "active" - // LocalNodeStateError ERROR - LocalNodeStateError LocalNodeState = "error" - // LocalNodeStateLocked LOCKED - LocalNodeStateLocked LocalNodeState = "locked" -) - -// Info represents generic information about swarm. -type Info struct { - NodeID string - NodeAddr string - - LocalNodeState LocalNodeState - ControlAvailable bool - Error string - - RemoteManagers []Peer - Nodes int `json:",omitempty"` - Managers int `json:",omitempty"` - - Cluster *ClusterInfo `json:",omitempty"` - - Warnings []string `json:",omitempty"` -} - -// Peer represents a peer. -type Peer struct { - NodeID string - Addr string -} - -// UpdateFlags contains flags for SwarmUpdate. -type UpdateFlags struct { - RotateWorkerToken bool - RotateManagerToken bool - RotateManagerUnlockKey bool -} diff --git a/vendor/github.com/docker/docker/api/types/swarm/task.go b/vendor/github.com/docker/docker/api/types/swarm/task.go deleted file mode 100644 index a6f7ab7b5c7..00000000000 --- a/vendor/github.com/docker/docker/api/types/swarm/task.go +++ /dev/null @@ -1,206 +0,0 @@ -package swarm // import "github.com/docker/docker/api/types/swarm" - -import ( - "time" - - "github.com/docker/docker/api/types/swarm/runtime" -) - -// TaskState represents the state of a task. -type TaskState string - -const ( - // TaskStateNew NEW - TaskStateNew TaskState = "new" - // TaskStateAllocated ALLOCATED - TaskStateAllocated TaskState = "allocated" - // TaskStatePending PENDING - TaskStatePending TaskState = "pending" - // TaskStateAssigned ASSIGNED - TaskStateAssigned TaskState = "assigned" - // TaskStateAccepted ACCEPTED - TaskStateAccepted TaskState = "accepted" - // TaskStatePreparing PREPARING - TaskStatePreparing TaskState = "preparing" - // TaskStateReady READY - TaskStateReady TaskState = "ready" - // TaskStateStarting STARTING - TaskStateStarting TaskState = "starting" - // TaskStateRunning RUNNING - TaskStateRunning TaskState = "running" - // TaskStateComplete COMPLETE - TaskStateComplete TaskState = "complete" - // TaskStateShutdown SHUTDOWN - TaskStateShutdown TaskState = "shutdown" - // TaskStateFailed FAILED - TaskStateFailed TaskState = "failed" - // TaskStateRejected REJECTED - TaskStateRejected TaskState = "rejected" - // TaskStateRemove REMOVE - TaskStateRemove TaskState = "remove" - // TaskStateOrphaned ORPHANED - TaskStateOrphaned TaskState = "orphaned" -) - -// Task represents a task. -type Task struct { - ID string - Meta - Annotations - - Spec TaskSpec `json:",omitempty"` - ServiceID string `json:",omitempty"` - Slot int `json:",omitempty"` - NodeID string `json:",omitempty"` - Status TaskStatus `json:",omitempty"` - DesiredState TaskState `json:",omitempty"` - NetworksAttachments []NetworkAttachment `json:",omitempty"` - GenericResources []GenericResource `json:",omitempty"` - - // JobIteration is the JobIteration of the Service that this Task was - // spawned from, if the Service is a ReplicatedJob or GlobalJob. This is - // used to determine which Tasks belong to which run of the job. This field - // is absent if the Service mode is Replicated or Global. - JobIteration *Version `json:",omitempty"` -} - -// TaskSpec represents the spec of a task. -type TaskSpec struct { - // ContainerSpec, NetworkAttachmentSpec, and PluginSpec are mutually exclusive. - // PluginSpec is only used when the `Runtime` field is set to `plugin` - // NetworkAttachmentSpec is used if the `Runtime` field is set to - // `attachment`. - ContainerSpec *ContainerSpec `json:",omitempty"` - PluginSpec *runtime.PluginSpec `json:",omitempty"` - NetworkAttachmentSpec *NetworkAttachmentSpec `json:",omitempty"` - - Resources *ResourceRequirements `json:",omitempty"` - RestartPolicy *RestartPolicy `json:",omitempty"` - Placement *Placement `json:",omitempty"` - Networks []NetworkAttachmentConfig `json:",omitempty"` - - // LogDriver specifies the LogDriver to use for tasks created from this - // spec. If not present, the one on cluster default on swarm.Spec will be - // used, finally falling back to the engine default if not specified. - LogDriver *Driver `json:",omitempty"` - - // ForceUpdate is a counter that triggers an update even if no relevant - // parameters have been changed. - ForceUpdate uint64 - - Runtime RuntimeType `json:",omitempty"` -} - -// Resources represents resources (CPU/Memory) which can be advertised by a -// node and requested to be reserved for a task. -type Resources struct { - NanoCPUs int64 `json:",omitempty"` - MemoryBytes int64 `json:",omitempty"` - GenericResources []GenericResource `json:",omitempty"` -} - -// Limit describes limits on resources which can be requested by a task. -type Limit struct { - NanoCPUs int64 `json:",omitempty"` - MemoryBytes int64 `json:",omitempty"` - Pids int64 `json:",omitempty"` -} - -// GenericResource represents a "user defined" resource which can -// be either an integer (e.g: SSD=3) or a string (e.g: SSD=sda1) -type GenericResource struct { - NamedResourceSpec *NamedGenericResource `json:",omitempty"` - DiscreteResourceSpec *DiscreteGenericResource `json:",omitempty"` -} - -// NamedGenericResource represents a "user defined" resource which is defined -// as a string. -// "Kind" is used to describe the Kind of a resource (e.g: "GPU", "FPGA", "SSD", ...) -// Value is used to identify the resource (GPU="UUID-1", FPGA="/dev/sdb5", ...) -type NamedGenericResource struct { - Kind string `json:",omitempty"` - Value string `json:",omitempty"` -} - -// DiscreteGenericResource represents a "user defined" resource which is defined -// as an integer -// "Kind" is used to describe the Kind of a resource (e.g: "GPU", "FPGA", "SSD", ...) -// Value is used to count the resource (SSD=5, HDD=3, ...) -type DiscreteGenericResource struct { - Kind string `json:",omitempty"` - Value int64 `json:",omitempty"` -} - -// ResourceRequirements represents resources requirements. -type ResourceRequirements struct { - Limits *Limit `json:",omitempty"` - Reservations *Resources `json:",omitempty"` -} - -// Placement represents orchestration parameters. -type Placement struct { - Constraints []string `json:",omitempty"` - Preferences []PlacementPreference `json:",omitempty"` - MaxReplicas uint64 `json:",omitempty"` - - // Platforms stores all the platforms that the image can run on. - // This field is used in the platform filter for scheduling. If empty, - // then the platform filter is off, meaning there are no scheduling restrictions. - Platforms []Platform `json:",omitempty"` -} - -// PlacementPreference provides a way to make the scheduler aware of factors -// such as topology. -type PlacementPreference struct { - Spread *SpreadOver -} - -// SpreadOver is a scheduling preference that instructs the scheduler to spread -// tasks evenly over groups of nodes identified by labels. -type SpreadOver struct { - // label descriptor, such as engine.labels.az - SpreadDescriptor string -} - -// RestartPolicy represents the restart policy. -type RestartPolicy struct { - Condition RestartPolicyCondition `json:",omitempty"` - Delay *time.Duration `json:",omitempty"` - MaxAttempts *uint64 `json:",omitempty"` - Window *time.Duration `json:",omitempty"` -} - -// RestartPolicyCondition represents when to restart. -type RestartPolicyCondition string - -const ( - // RestartPolicyConditionNone NONE - RestartPolicyConditionNone RestartPolicyCondition = "none" - // RestartPolicyConditionOnFailure ON_FAILURE - RestartPolicyConditionOnFailure RestartPolicyCondition = "on-failure" - // RestartPolicyConditionAny ANY - RestartPolicyConditionAny RestartPolicyCondition = "any" -) - -// TaskStatus represents the status of a task. -type TaskStatus struct { - Timestamp time.Time `json:",omitempty"` - State TaskState `json:",omitempty"` - Message string `json:",omitempty"` - Err string `json:",omitempty"` - ContainerStatus *ContainerStatus `json:",omitempty"` - PortStatus PortStatus `json:",omitempty"` -} - -// ContainerStatus represents the status of a container. -type ContainerStatus struct { - ContainerID string - PID int - ExitCode int -} - -// PortStatus represents the port status of a task's host ports whose -// service has published host ports -type PortStatus struct { - Ports []PortConfig `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/time/duration_convert.go b/vendor/github.com/docker/docker/api/types/time/duration_convert.go deleted file mode 100644 index 84b6f073224..00000000000 --- a/vendor/github.com/docker/docker/api/types/time/duration_convert.go +++ /dev/null @@ -1,12 +0,0 @@ -package time // import "github.com/docker/docker/api/types/time" - -import ( - "strconv" - "time" -) - -// DurationToSecondsString converts the specified duration to the number -// seconds it represents, formatted as a string. -func DurationToSecondsString(duration time.Duration) string { - return strconv.FormatFloat(duration.Seconds(), 'f', 0, 64) -} diff --git a/vendor/github.com/docker/docker/api/types/time/timestamp.go b/vendor/github.com/docker/docker/api/types/time/timestamp.go deleted file mode 100644 index ea3495efeb8..00000000000 --- a/vendor/github.com/docker/docker/api/types/time/timestamp.go +++ /dev/null @@ -1,129 +0,0 @@ -package time // import "github.com/docker/docker/api/types/time" - -import ( - "fmt" - "math" - "strconv" - "strings" - "time" -) - -// These are additional predefined layouts for use in Time.Format and Time.Parse -// with --since and --until parameters for `docker logs` and `docker events` -const ( - rFC3339Local = "2006-01-02T15:04:05" // RFC3339 with local timezone - rFC3339NanoLocal = "2006-01-02T15:04:05.999999999" // RFC3339Nano with local timezone - dateWithZone = "2006-01-02Z07:00" // RFC3339 with time at 00:00:00 - dateLocal = "2006-01-02" // RFC3339 with local timezone and time at 00:00:00 -) - -// GetTimestamp tries to parse given string as golang duration, -// then RFC3339 time and finally as a Unix timestamp. If -// any of these were successful, it returns a Unix timestamp -// as string otherwise returns the given value back. -// In case of duration input, the returned timestamp is computed -// as the given reference time minus the amount of the duration. -func GetTimestamp(value string, reference time.Time) (string, error) { - if d, err := time.ParseDuration(value); value != "0" && err == nil { - return strconv.FormatInt(reference.Add(-d).Unix(), 10), nil - } - - var format string - // if the string has a Z or a + or three dashes use parse otherwise use parseinlocation - parseInLocation := !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3) - - if strings.Contains(value, ".") { - if parseInLocation { - format = rFC3339NanoLocal - } else { - format = time.RFC3339Nano - } - } else if strings.Contains(value, "T") { - // we want the number of colons in the T portion of the timestamp - tcolons := strings.Count(value, ":") - // if parseInLocation is off and we have a +/- zone offset (not Z) then - // there will be an extra colon in the input for the tz offset subtract that - // colon from the tcolons count - if !parseInLocation && !strings.ContainsAny(value, "zZ") && tcolons > 0 { - tcolons-- - } - if parseInLocation { - switch tcolons { - case 0: - format = "2006-01-02T15" - case 1: - format = "2006-01-02T15:04" - default: - format = rFC3339Local - } - } else { - switch tcolons { - case 0: - format = "2006-01-02T15Z07:00" - case 1: - format = "2006-01-02T15:04Z07:00" - default: - format = time.RFC3339 - } - } - } else if parseInLocation { - format = dateLocal - } else { - format = dateWithZone - } - - var t time.Time - var err error - - if parseInLocation { - t, err = time.ParseInLocation(format, value, time.FixedZone(reference.Zone())) - } else { - t, err = time.Parse(format, value) - } - - if err != nil { - // if there is a `-` then it's an RFC3339 like timestamp - if strings.Contains(value, "-") { - return "", err // was probably an RFC3339 like timestamp but the parser failed with an error - } - if _, _, err := parseTimestamp(value); err != nil { - return "", fmt.Errorf("failed to parse value as time or duration: %q", value) - } - return value, nil // unix timestamp in and out case (meaning: the value passed at the command line is already in the right format for passing to the server) - } - - return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil -} - -// ParseTimestamps returns seconds and nanoseconds from a timestamp that has the -// format "%d.%09d", time.Unix(), int64(time.Nanosecond())) -// if the incoming nanosecond portion is longer or shorter than 9 digits it is -// converted to nanoseconds. The expectation is that the seconds and -// seconds will be used to create a time variable. For example: -// seconds, nanoseconds, err := ParseTimestamp("1136073600.000000001",0) -// if err == nil since := time.Unix(seconds, nanoseconds) -// returns seconds as def(aultSeconds) if value == "" -func ParseTimestamps(value string, def int64) (int64, int64, error) { - if value == "" { - return def, 0, nil - } - return parseTimestamp(value) -} - -func parseTimestamp(value string) (int64, int64, error) { - sa := strings.SplitN(value, ".", 2) - s, err := strconv.ParseInt(sa[0], 10, 64) - if err != nil { - return s, 0, err - } - if len(sa) != 2 { - return s, 0, nil - } - n, err := strconv.ParseInt(sa[1], 10, 64) - if err != nil { - return s, n, err - } - // should already be in nanoseconds but just in case convert n to nanoseconds - n = int64(float64(n) * math.Pow(float64(10), float64(9-len(sa[1])))) - return s, n, nil -} diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go deleted file mode 100644 index e3a159912e2..00000000000 --- a/vendor/github.com/docker/docker/api/types/types.go +++ /dev/null @@ -1,635 +0,0 @@ -package types // import "github.com/docker/docker/api/types" - -import ( - "errors" - "fmt" - "io" - "os" - "strings" - "time" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/filters" - "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/swarm" - "github.com/docker/go-connections/nat" -) - -// RootFS returns Image's RootFS description including the layer IDs. -type RootFS struct { - Type string - Layers []string `json:",omitempty"` - BaseLayer string `json:",omitempty"` -} - -// ImageInspect contains response of Engine API: -// GET "/images/{name:.*}/json" -type ImageInspect struct { - ID string `json:"Id"` - RepoTags []string - RepoDigests []string - Parent string - Comment string - Created string - Container string - ContainerConfig *container.Config - DockerVersion string - Author string - Config *container.Config - Architecture string - Variant string `json:",omitempty"` - Os string - OsVersion string `json:",omitempty"` - Size int64 - VirtualSize int64 - GraphDriver GraphDriverData - RootFS RootFS - Metadata ImageMetadata -} - -// ImageMetadata contains engine-local data about the image -type ImageMetadata struct { - LastTagTime time.Time `json:",omitempty"` -} - -// 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"` - } - NetworkSettings *SummaryNetworkSettings - Mounts []MountPoint -} - -// CopyConfig contains request body of Engine API: -// POST "/containers/"+containerID+"/copy" -type CopyConfig struct { - Resource string -} - -// ContainerPathStat is used to encode the header from -// GET "/containers/{name:.*}/archive" -// "Name" is the file or directory name. -type ContainerPathStat struct { - Name string `json:"name"` - Size int64 `json:"size"` - Mode os.FileMode `json:"mode"` - Mtime time.Time `json:"mtime"` - LinkTarget string `json:"linkTarget"` -} - -// ContainerStats contains response of Engine API: -// GET "/stats" -type ContainerStats struct { - Body io.ReadCloser `json:"body"` - OSType string `json:"ostype"` -} - -// Ping contains response of Engine API: -// GET "/_ping" -type Ping struct { - APIVersion string - OSType string - Experimental bool - BuilderVersion BuilderVersion -} - -// ComponentVersion describes the version information for a specific component. -type ComponentVersion struct { - Name string - Version string - Details map[string]string `json:",omitempty"` -} - -// Version contains response of Engine API: -// GET "/version" -type Version struct { - Platform struct{ Name string } `json:",omitempty"` - Components []ComponentVersion `json:",omitempty"` - - // The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility - - Version string - APIVersion string `json:"ApiVersion"` - MinAPIVersion string `json:"MinAPIVersion,omitempty"` - GitCommit string - GoVersion string - Os string - Arch string - KernelVersion string `json:",omitempty"` - Experimental bool `json:",omitempty"` - BuildTime string `json:",omitempty"` -} - -// 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. -} - -// Info contains response of Engine API: -// GET "/info" -type Info struct { - ID string - Containers int - ContainersRunning int - ContainersPaused int - ContainersStopped int - Images int - Driver string - DriverStatus [][2]string - SystemStatus [][2]string `json:",omitempty"` // SystemStatus is only propagated by the Swarm standalone API - Plugins PluginsInfo - MemoryLimit bool - SwapLimit bool - KernelMemory bool // Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes - KernelMemoryTCP bool - CPUCfsPeriod bool `json:"CpuCfsPeriod"` - CPUCfsQuota bool `json:"CpuCfsQuota"` - CPUShares bool - CPUSet bool - PidsLimit bool - IPv4Forwarding bool - BridgeNfIptables bool - BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` - Debug bool - NFd int - OomKillDisable bool - NGoroutines int - SystemTime string - LoggingDriver string - CgroupDriver string - CgroupVersion string `json:",omitempty"` - NEventsListener int - KernelVersion string - OperatingSystem string - OSVersion string - OSType string - Architecture string - IndexServerAddress string - RegistryConfig *registry.ServiceConfig - NCPU int - MemTotal int64 - GenericResources []swarm.GenericResource - DockerRootDir string - HTTPProxy string `json:"HttpProxy"` - HTTPSProxy string `json:"HttpsProxy"` - NoProxy string - Name string - Labels []string - ExperimentalBuild bool - ServerVersion string - ClusterStore string `json:",omitempty"` // Deprecated: host-discovery and overlay networks with external k/v stores are deprecated - ClusterAdvertise string `json:",omitempty"` // Deprecated: host-discovery and overlay networks with external k/v stores are deprecated - Runtimes map[string]Runtime - DefaultRuntime string - Swarm swarm.Info - // LiveRestoreEnabled determines whether containers should be kept - // running when the daemon is shutdown or upon daemon start if - // running containers are detected - LiveRestoreEnabled bool - Isolation container.Isolation - InitBinary string - ContainerdCommit Commit - RuncCommit Commit - InitCommit Commit - SecurityOptions []string - ProductLicense string `json:",omitempty"` - DefaultAddressPools []NetworkAddressPool `json:",omitempty"` - Warnings []string -} - -// KeyValue holds a key/value pair -type KeyValue struct { - Key, Value string -} - -// NetworkAddressPool is a temp struct used by Info struct -type NetworkAddressPool struct { - Base string - Size int -} - -// SecurityOpt contains the name and options of a security option -type SecurityOpt struct { - Name string - Options []KeyValue -} - -// DecodeSecurityOptions decodes a security options string slice to a type safe -// SecurityOpt -func DecodeSecurityOptions(opts []string) ([]SecurityOpt, error) { - so := []SecurityOpt{} - for _, opt := range opts { - // support output from a < 1.13 docker daemon - if !strings.Contains(opt, "=") { - so = append(so, SecurityOpt{Name: opt}) - continue - } - secopt := SecurityOpt{} - split := strings.Split(opt, ",") - for _, s := range split { - kv := strings.SplitN(s, "=", 2) - if len(kv) != 2 { - return nil, fmt.Errorf("invalid security option %q", s) - } - if kv[0] == "" || kv[1] == "" { - return nil, errors.New("invalid empty security option") - } - if kv[0] == "name" { - secopt.Name = kv[1] - continue - } - secopt.Options = append(secopt.Options, KeyValue{Key: kv[0], Value: kv[1]}) - } - so = append(so, secopt) - } - return so, nil -} - -// PluginsInfo is a temp struct holding Plugins name -// registered with docker daemon. It is used by Info struct -type PluginsInfo struct { - // List of Volume plugins registered - Volume []string - // List of Network plugins registered - Network []string - // List of Authorization plugins registered - Authorization []string - // List of Log plugins registered - Log []string -} - -// ExecStartCheck is a temp struct used by execStart -// Config fields is part of ExecConfig in runconfig package -type ExecStartCheck struct { - // ExecStart will first check if it's detached - Detach bool - // Check if there's a tty - Tty bool -} - -// 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"` -} - -// ContainerNode stores information about the node that a container -// is running on. It's only used by the Docker Swarm standalone API -type ContainerNode struct { - ID string - IPAddress string `json:"IP"` - Addr string - Name string - Cpus int - Memory int64 - Labels map[string]string -} - -// 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"` // Node is only propagated by Docker Swarm standalone API - 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 basic information about networks -type NetworkSettingsBase struct { - Bridge string // Bridge is the Bridge name the network uses(e.g. `docker0`) - SandboxID string // SandboxID uniquely represents a container's network stack - HairpinMode bool // HairpinMode specifies if hairpin NAT should be enabled on the virtual interface - LinkLocalIPv6Address string // LinkLocalIPv6Address is an IPv6 unicast address using the link-local prefix - LinkLocalIPv6PrefixLen int // LinkLocalIPv6PrefixLen is the prefix length of an IPv6 unicast address - Ports nat.PortMap // Ports is a collection of PortBinding indexed by Port - SandboxKey string // SandboxKey identifies the sandbox - SecondaryIPAddresses []network.Address - SecondaryIPv6Addresses []network.Address -} - -// 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 mount.Type `json:",omitempty"` - Name string `json:",omitempty"` - Source string - Destination string - Driver string `json:",omitempty"` - Mode string - RW bool - Propagation mount.Propagation -} - -// NetworkResource is the body of the "get network" http response message -type NetworkResource struct { - Name string // Name is the requested name of the network - ID string `json:"Id"` // ID uniquely identifies a network on a single machine - 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 - IPAM network.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. - Ingress bool // Ingress indicates the network is providing the routing-mesh for the swarm cluster. - ConfigFrom network.ConfigReference // ConfigFrom specifies the source which will provide the configuration for this network. - ConfigOnly bool // ConfigOnly networks are place-holder networks for network configurations to be used by other networks. ConfigOnly networks cannot be used directly to run containers or services. - Containers map[string]EndpointResource // Containers contains endpoints belonging to the network - Options map[string]string // Options holds the network specific options to use for when creating the network - Labels map[string]string // Labels holds metadata specific to the network being created - Peers []network.PeerInfo `json:",omitempty"` // List of peer nodes for an overlay network - Services map[string]network.ServiceInfo `json:",omitempty"` -} - -// EndpointResource contains network resources allocated and used for a container in a network -type EndpointResource struct { - Name string - EndpointID string - MacAddress string - IPv4Address string - IPv6Address string -} - -// NetworkCreate is the expected body of the "create network" http request message -type NetworkCreate struct { - // Check for networks with duplicate names. - // Network is primarily keyed based on a random ID and not on the name. - // Network name is strictly a user-friendly alias to the network - // which is uniquely identified using ID. - // And there is no guaranteed way to check for duplicates. - // Option CheckDuplicate is there to provide a best effort checking of any networks - // which has the same name but it is not guaranteed to catch all name collisions. - CheckDuplicate bool - Driver string - Scope string - EnableIPv6 bool - IPAM *network.IPAM - Internal bool - Attachable bool - Ingress bool - ConfigOnly bool - ConfigFrom *network.ConfigReference - Options map[string]string - Labels map[string]string -} - -// NetworkCreateRequest is the request message sent to the server for network create call. -type NetworkCreateRequest struct { - NetworkCreate - Name string -} - -// NetworkCreateResponse is the response message sent by the server for network create call -type NetworkCreateResponse struct { - ID string `json:"Id"` - Warning string -} - -// NetworkConnect represents the data to be used to connect a container to the network -type NetworkConnect struct { - Container string - EndpointConfig *network.EndpointSettings `json:",omitempty"` -} - -// NetworkDisconnect represents the data to be used to disconnect a container from the network -type NetworkDisconnect struct { - Container string - Force bool -} - -// NetworkInspectOptions holds parameters to inspect network -type NetworkInspectOptions struct { - Scope string - Verbose bool -} - -// Checkpoint represents the details of a checkpoint -type Checkpoint struct { - Name string // Name is the name of the checkpoint -} - -// Runtime describes an OCI runtime -type Runtime struct { - Path string `json:"path"` - Args []string `json:"runtimeArgs,omitempty"` - - // This is exposed here only for internal use - // It is not currently supported to specify custom shim configs - Shim *ShimConfig `json:"-"` -} - -// ShimConfig is used by runtime to configure containerd shims -type ShimConfig struct { - Binary string - Opts interface{} -} - -// DiskUsage contains response of Engine API: -// GET "/system/df" -type DiskUsage struct { - LayersSize int64 - Images []*ImageSummary - Containers []*Container - Volumes []*Volume - BuildCache []*BuildCache - BuilderSize int64 // deprecated -} - -// ContainersPruneReport contains the response for Engine API: -// POST "/containers/prune" -type ContainersPruneReport struct { - ContainersDeleted []string - SpaceReclaimed uint64 -} - -// VolumesPruneReport contains the response for Engine API: -// POST "/volumes/prune" -type VolumesPruneReport struct { - VolumesDeleted []string - SpaceReclaimed uint64 -} - -// ImagesPruneReport contains the response for Engine API: -// POST "/images/prune" -type ImagesPruneReport struct { - ImagesDeleted []ImageDeleteResponseItem - SpaceReclaimed uint64 -} - -// BuildCachePruneReport contains the response for Engine API: -// POST "/build/prune" -type BuildCachePruneReport struct { - CachesDeleted []string - SpaceReclaimed uint64 -} - -// NetworksPruneReport contains the response for Engine API: -// POST "/networks/prune" -type NetworksPruneReport struct { - NetworksDeleted []string -} - -// SecretCreateResponse contains the information returned to a client -// on the creation of a new secret. -type SecretCreateResponse struct { - // ID is the id of the created secret. - ID string -} - -// SecretListOptions holds parameters to list secrets -type SecretListOptions struct { - Filters filters.Args -} - -// ConfigCreateResponse contains the information returned to a client -// on the creation of a new config. -type ConfigCreateResponse struct { - // ID is the id of the created config. - ID string -} - -// ConfigListOptions holds parameters to list configs -type ConfigListOptions struct { - Filters filters.Args -} - -// PushResult contains the tag, manifest digest, and manifest size from the -// push. It's used to signal this information to the trust code in the client -// so it can sign the manifest if necessary. -type PushResult struct { - Tag string - Digest string - Size int -} - -// BuildResult contains the image id of a successful build -type BuildResult struct { - ID string -} - -// BuildCache contains information about a build cache record -type BuildCache struct { - ID string - Parent string - Type string - Description string - InUse bool - Shared bool - Size int64 - CreatedAt time.Time - LastUsedAt *time.Time - UsageCount int -} - -// BuildCachePruneOptions hold parameters to prune the build cache -type BuildCachePruneOptions struct { - All bool - KeepStorage int64 - Filters filters.Args -} diff --git a/vendor/github.com/docker/docker/api/types/versions/README.md b/vendor/github.com/docker/docker/api/types/versions/README.md deleted file mode 100644 index 1ef911edb0f..00000000000 --- a/vendor/github.com/docker/docker/api/types/versions/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Legacy API type versions - -This package includes types for legacy API versions. The stable version of the API types live in `api/types/*.go`. - -Consider moving a type here when you need to keep backwards compatibility in the API. This legacy types are organized by the latest API version they appear in. For instance, types in the `v1p19` package are valid for API versions below or equal `1.19`. Types in the `v1p20` package are valid for the API version `1.20`, since the versions below that will use the legacy types in `v1p19`. - -## Package name conventions - -The package name convention is to use `v` as a prefix for the version number and `p`(patch) as a separator. We use this nomenclature due to a few restrictions in the Go package name convention: - -1. We cannot use `.` because it's interpreted by the language, think of `v1.20.CallFunction`. -2. We cannot use `_` because golint complains about it. The code is actually valid, but it looks probably more weird: `v1_20.CallFunction`. - -For instance, if you want to modify a type that was available in the version `1.21` of the API but it will have different fields in the version `1.22`, you want to create a new package under `api/types/versions/v1p21`. diff --git a/vendor/github.com/docker/docker/api/types/versions/compare.go b/vendor/github.com/docker/docker/api/types/versions/compare.go deleted file mode 100644 index 8ccb0aa92eb..00000000000 --- a/vendor/github.com/docker/docker/api/types/versions/compare.go +++ /dev/null @@ -1,62 +0,0 @@ -package versions // import "github.com/docker/docker/api/types/versions" - -import ( - "strconv" - "strings" -) - -// compare compares two version strings -// returns -1 if v1 < v2, 1 if v1 > v2, 0 otherwise. -func compare(v1, v2 string) int { - var ( - currTab = strings.Split(v1, ".") - otherTab = strings.Split(v2, ".") - ) - - max := len(currTab) - if len(otherTab) > max { - max = len(otherTab) - } - for i := 0; i < max; i++ { - var currInt, otherInt int - - if len(currTab) > i { - currInt, _ = strconv.Atoi(currTab[i]) - } - if len(otherTab) > i { - otherInt, _ = strconv.Atoi(otherTab[i]) - } - if currInt > otherInt { - return 1 - } - if otherInt > currInt { - return -1 - } - } - return 0 -} - -// LessThan checks if a version is less than another -func LessThan(v, other string) bool { - return compare(v, other) == -1 -} - -// LessThanOrEqualTo checks if a version is less than or equal to another -func LessThanOrEqualTo(v, other string) bool { - return compare(v, other) <= 0 -} - -// GreaterThan checks if a version is greater than another -func GreaterThan(v, other string) bool { - return compare(v, other) == 1 -} - -// GreaterThanOrEqualTo checks if a version is greater than or equal to another -func GreaterThanOrEqualTo(v, other string) bool { - return compare(v, other) >= 0 -} - -// Equal checks if a version is equal to another -func Equal(v, other string) bool { - return compare(v, other) == 0 -} diff --git a/vendor/github.com/docker/docker/api/types/volume.go b/vendor/github.com/docker/docker/api/types/volume.go deleted file mode 100644 index c69b08448df..00000000000 --- a/vendor/github.com/docker/docker/api/types/volume.go +++ /dev/null @@ -1,72 +0,0 @@ -package types - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -// Volume volume -// swagger:model Volume -type Volume struct { - - // Date/Time the volume was created. - CreatedAt string `json:"CreatedAt,omitempty"` - - // Name of the volume driver used by the volume. - // Required: true - Driver string `json:"Driver"` - - // User-defined key/value metadata. - // Required: true - Labels map[string]string `json:"Labels"` - - // Mount path of the volume on the host. - // Required: true - Mountpoint string `json:"Mountpoint"` - - // Name of the volume. - // Required: true - Name string `json:"Name"` - - // The driver specific options used when creating the volume. - // - // Required: true - Options map[string]string `json:"Options"` - - // The level at which the volume exists. Either `global` for cluster-wide, - // or `local` for machine level. - // - // Required: true - Scope string `json:"Scope"` - - // Low-level details about the volume, provided by the volume driver. - // Details are returned as a map with key/value pairs: - // `{"key":"value","key2":"value2"}`. - // - // The `Status` field is optional, and is omitted if the volume driver - // does not support this feature. - // - Status map[string]interface{} `json:"Status,omitempty"` - - // usage data - UsageData *VolumeUsageData `json:"UsageData,omitempty"` -} - -// VolumeUsageData Usage details about the volume. This information is used by the -// `GET /system/df` endpoint, and omitted in other endpoints. -// -// swagger:model VolumeUsageData -type VolumeUsageData struct { - - // The number of containers referencing this volume. This field - // is set to `-1` if the reference-count is not available. - // - // Required: true - RefCount int64 `json:"RefCount"` - - // Amount of disk space used by the volume (in bytes). This information - // is only available for volumes created with the `"local"` volume - // driver. For volumes created with other volume drivers, this field - // is set to `-1` ("not available") - // - // Required: true - Size int64 `json:"Size"` -} diff --git a/vendor/github.com/docker/docker/api/types/volume/volume_create.go b/vendor/github.com/docker/docker/api/types/volume/volume_create.go deleted file mode 100644 index 8538078dd66..00000000000 --- a/vendor/github.com/docker/docker/api/types/volume/volume_create.go +++ /dev/null @@ -1,31 +0,0 @@ -package volume // import "github.com/docker/docker/api/types/volume" - -// ---------------------------------------------------------------------------- -// Code generated by `swagger generate operation`. DO NOT EDIT. -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -// VolumeCreateBody Volume configuration -// swagger:model VolumeCreateBody -type VolumeCreateBody struct { - - // Name of the volume driver to use. - // Required: true - Driver string `json:"Driver"` - - // A mapping of driver options and values. These options are - // passed directly to the driver and are driver specific. - // - // Required: true - DriverOpts map[string]string `json:"DriverOpts"` - - // User-defined key/value metadata. - // Required: true - Labels map[string]string `json:"Labels"` - - // The new volume's name. If not specified, Docker generates a name. - // - // Required: true - Name string `json:"Name"` -} diff --git a/vendor/github.com/docker/docker/api/types/volume/volume_list.go b/vendor/github.com/docker/docker/api/types/volume/volume_list.go deleted file mode 100644 index be06179bf48..00000000000 --- a/vendor/github.com/docker/docker/api/types/volume/volume_list.go +++ /dev/null @@ -1,23 +0,0 @@ -package volume // import "github.com/docker/docker/api/types/volume" - -// ---------------------------------------------------------------------------- -// Code generated by `swagger generate operation`. DO NOT EDIT. -// -// See hack/generate-swagger-api.sh -// ---------------------------------------------------------------------------- - -import "github.com/docker/docker/api/types" - -// VolumeListOKBody Volume list response -// swagger:model VolumeListOKBody -type VolumeListOKBody struct { - - // List of volumes - // Required: true - Volumes []*types.Volume `json:"Volumes"` - - // Warnings that occurred when fetching the list of volumes. - // - // Required: true - Warnings []string `json:"Warnings"` -} diff --git a/vendor/github.com/docker/docker/client/README.md b/vendor/github.com/docker/docker/client/README.md deleted file mode 100644 index 992f18117df..00000000000 --- a/vendor/github.com/docker/docker/client/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Go client for the Docker Engine API - -The `docker` command uses this package to communicate with the daemon. It can also be used by your own Go applications to do anything the command-line interface does – running containers, pulling images, managing swarms, etc. - -For example, to list running containers (the equivalent of `docker ps`): - -```go -package main - -import ( - "context" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" -) - -func main() { - cli, err := client.NewClientWithOpts(client.FromEnv) - if err != nil { - panic(err) - } - - containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) - if err != nil { - panic(err) - } - - for _, container := range containers { - fmt.Printf("%s %s\n", container.ID[:10], container.Image) - } -} -``` - -[Full documentation is available on GoDoc.](https://godoc.org/github.com/docker/docker/client) diff --git a/vendor/github.com/docker/docker/client/build_cancel.go b/vendor/github.com/docker/docker/client/build_cancel.go deleted file mode 100644 index 3aae43e3d17..00000000000 --- a/vendor/github.com/docker/docker/client/build_cancel.go +++ /dev/null @@ -1,16 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" -) - -// BuildCancel requests the daemon to cancel ongoing build request -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) - return err -} diff --git a/vendor/github.com/docker/docker/client/build_prune.go b/vendor/github.com/docker/docker/client/build_prune.go deleted file mode 100644 index 397d67cdcf1..00000000000 --- a/vendor/github.com/docker/docker/client/build_prune.go +++ /dev/null @@ -1,45 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/pkg/errors" -) - -// BuildCachePrune requests the daemon to delete unused cache data -func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) { - if err := cli.NewVersionError("1.31", "build prune"); err != nil { - return nil, err - } - - report := types.BuildCachePruneReport{} - - query := url.Values{} - if opts.All { - query.Set("all", "1") - } - query.Set("keep-storage", fmt.Sprintf("%d", opts.KeepStorage)) - filters, err := filters.ToJSON(opts.Filters) - if err != nil { - return nil, errors.Wrap(err, "prune could not marshal filters option") - } - query.Set("filters", filters) - - serverResp, err := cli.post(ctx, "/build/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) - - if err != nil { - return nil, err - } - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return nil, fmt.Errorf("Error retrieving disk usage: %v", err) - } - - return &report, nil -} diff --git a/vendor/github.com/docker/docker/client/checkpoint_create.go b/vendor/github.com/docker/docker/client/checkpoint_create.go deleted file mode 100644 index 921024fe4fb..00000000000 --- a/vendor/github.com/docker/docker/client/checkpoint_create.go +++ /dev/null @@ -1,14 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - - "github.com/docker/docker/api/types" -) - -// CheckpointCreate creates a checkpoint from the given container with the given name -func (cli *Client) CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error { - resp, err := cli.post(ctx, "/containers/"+container+"/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 deleted file mode 100644 index 54f55fa76e6..00000000000 --- a/vendor/github.com/docker/docker/client/checkpoint_delete.go +++ /dev/null @@ -1,20 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types" -) - -// CheckpointDelete deletes the checkpoint with the given name from the given container -func (cli *Client) CheckpointDelete(ctx context.Context, containerID string, options types.CheckpointDeleteOptions) error { - query := url.Values{} - if options.CheckpointDir != "" { - query.Set("dir", options.CheckpointDir) - } - - resp, err := cli.delete(ctx, "/containers/"+containerID+"/checkpoints/"+options.CheckpointID, query, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/checkpoint_list.go b/vendor/github.com/docker/docker/client/checkpoint_list.go deleted file mode 100644 index 66d46dd161b..00000000000 --- a/vendor/github.com/docker/docker/client/checkpoint_list.go +++ /dev/null @@ -1,28 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" -) - -// CheckpointList returns the checkpoints of the given container in the docker host -func (cli *Client) CheckpointList(ctx context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) { - var checkpoints []types.Checkpoint - - query := url.Values{} - if options.CheckpointDir != "" { - query.Set("dir", options.CheckpointDir) - } - - resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return checkpoints, wrapResponseError(err, resp, "container", container) - } - - 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 deleted file mode 100644 index 21edf1fa1fc..00000000000 --- a/vendor/github.com/docker/docker/client/client.go +++ /dev/null @@ -1,310 +0,0 @@ -/* -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/ - -Usage - -You use the library by creating a client object and calling methods on it. The -client can be created either from environment variables with NewClientWithOpts(client.FromEnv), -or configured manually with NewClient(). - -For example, to list running containers (the equivalent of "docker ps"): - - package main - - import ( - "context" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - ) - - func main() { - cli, err := client.NewClientWithOpts(client.FromEnv) - if err != nil { - panic(err) - } - - containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) - if err != nil { - panic(err) - } - - for _, container := range containers { - fmt.Printf("%s %s\n", container.ID[:10], container.Image) - } - } - -*/ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "fmt" - "net" - "net/http" - "net/url" - "path" - "strings" - - "github.com/docker/docker/api" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/docker/go-connections/sockets" - "github.com/pkg/errors" -) - -// ErrRedirect is the error returned by checkRedirect when the request is non-GET. -var ErrRedirect = errors.New("unexpected redirect in response") - -// Client is the API client that performs all operations -// against a docker server. -type Client struct { - // scheme sets the scheme for the client - scheme string - // host holds the server address to connect to - host string - // proto holds the client protocol i.e. unix. - proto string - // addr holds the client address. - addr string - // basePath holds the path to prepend to the requests. - basePath string - // client used to send and receive http requests. - client *http.Client - // version of the server to talk to. - version string - // custom http headers configured by users. - customHTTPHeaders map[string]string - // manualOverride is set to true when the version was set by users. - manualOverride bool - - // negotiateVersion indicates if the client should automatically negotiate - // the API version to use when making requests. API version negotiation is - // performed on the first request, after which negotiated is set to "true" - // so that subsequent requests do not re-negotiate. - negotiateVersion bool - - // negotiated indicates that API version negotiation took place - negotiated bool -} - -// CheckRedirect specifies the policy for dealing with redirect responses: -// If the request is non-GET return `ErrRedirect`. Otherwise use the last response. -// -// Go 1.8 changes behavior for HTTP redirects (specifically 301, 307, and 308) in the client . -// The Docker client (and by extension docker API client) can be made to send a request -// like POST /containers//start where what would normally be in the name section of the URL is empty. -// This triggers an HTTP 301 from the daemon. -// In go 1.8 this 301 will be converted to a GET request, and ends up getting a 404 from the daemon. -// This behavior change manifests in the client in that before the 301 was not followed and -// the client did not generate an error, but now results in a message like Error response from daemon: page not found. -func CheckRedirect(req *http.Request, via []*http.Request) error { - if via[0].Method == http.MethodGet { - return http.ErrUseLastResponse - } - return ErrRedirect -} - -// NewClientWithOpts initializes a new API client with default values. It takes functors -// to modify values when creating it, like `NewClientWithOpts(WithVersion(…))` -// It also initializes the custom http headers to add to each request. -// -// It won't send any version information if the version number is empty. It is -// highly recommended that you set a version or your client may break if the -// server is upgraded. -func NewClientWithOpts(ops ...Opt) (*Client, error) { - client, err := defaultHTTPClient(DefaultDockerHost) - if err != nil { - return nil, err - } - c := &Client{ - host: DefaultDockerHost, - version: api.DefaultVersion, - client: client, - proto: defaultProto, - addr: defaultAddr, - } - - for _, op := range ops { - if err := op(c); err != nil { - return nil, err - } - } - - if _, ok := c.client.Transport.(http.RoundTripper); !ok { - return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", c.client.Transport) - } - if c.scheme == "" { - c.scheme = "http" - - tlsConfig := resolveTLSConfig(c.client.Transport) - if tlsConfig != nil { - // TODO(stevvooe): This isn't really the right way to write clients in Go. - // `NewClient` should probably only take an `*http.Client` and work from there. - // Unfortunately, the model of having a host-ish/url-thingy as the connection - // string has us confusing protocol and transport layers. We continue doing - // this to avoid breaking existing clients but this should be addressed. - c.scheme = "https" - } - } - - return c, nil -} - -func defaultHTTPClient(host string) (*http.Client, error) { - url, err := ParseHostURL(host) - if err != nil { - return nil, err - } - transport := new(http.Transport) - sockets.ConfigureTransport(transport, url.Scheme, url.Host) - return &http.Client{ - Transport: transport, - CheckRedirect: CheckRedirect, - }, nil -} - -// Close the transport used by the client -func (cli *Client) Close() error { - if t, ok := cli.client.Transport.(*http.Transport); ok { - t.CloseIdleConnections() - } - return nil -} - -// getAPIPath returns the versioned request path to call the api. -// It appends the query parameters to the path if they are not empty. -func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string { - var apiPath string - if cli.negotiateVersion && !cli.negotiated { - cli.NegotiateAPIVersion(ctx) - } - if cli.version != "" { - v := strings.TrimPrefix(cli.version, "v") - apiPath = path.Join(cli.basePath, "/v"+v, p) - } else { - apiPath = path.Join(cli.basePath, p) - } - return (&url.URL{Path: apiPath, RawQuery: query.Encode()}).String() -} - -// ClientVersion returns the API version used by this client. -func (cli *Client) ClientVersion() string { - return cli.version -} - -// NegotiateAPIVersion queries the API and updates the version to match the -// API version. Any errors are silently ignored. If a manual override is in place, -// either through the `DOCKER_API_VERSION` environment variable, or if the client -// was initialized with a fixed version (`opts.WithVersion(xx)`), no negotiation -// will be performed. -func (cli *Client) NegotiateAPIVersion(ctx context.Context) { - if !cli.manualOverride { - ping, _ := cli.Ping(ctx) - cli.negotiateAPIVersionPing(ping) - } -} - -// NegotiateAPIVersionPing updates the client version to match the Ping.APIVersion -// if the ping version is less than the default version. If a manual override is -// in place, either through the `DOCKER_API_VERSION` environment variable, or if -// the client was initialized with a fixed version (`opts.WithVersion(xx)`), no -// negotiation is performed. -func (cli *Client) NegotiateAPIVersionPing(p types.Ping) { - if !cli.manualOverride { - cli.negotiateAPIVersionPing(p) - } -} - -// negotiateAPIVersionPing queries the API and updates the version to match the -// API version. Any errors are silently ignored. -func (cli *Client) negotiateAPIVersionPing(p types.Ping) { - // try the latest version before versioning headers existed - if p.APIVersion == "" { - p.APIVersion = "1.24" - } - - // if the client is not initialized with a version, start with the latest supported version - if cli.version == "" { - cli.version = api.DefaultVersion - } - - // if server version is lower than the client version, downgrade - if versions.LessThan(p.APIVersion, cli.version) { - cli.version = p.APIVersion - } - - // Store the results, so that automatic API version negotiation (if enabled) - // won't be performed on the next request. - if cli.negotiateVersion { - cli.negotiated = true - } -} - -// DaemonHost returns the host address used by the client -func (cli *Client) DaemonHost() string { - return cli.host -} - -// HTTPClient returns a copy of the HTTP client bound to the server -func (cli *Client) HTTPClient() *http.Client { - c := *cli.client - return &c -} - -// ParseHostURL parses a url string, validates the string is a host url, and -// returns the parsed URL -func ParseHostURL(host string) (*url.URL, error) { - protoAddrParts := strings.SplitN(host, "://", 2) - if len(protoAddrParts) == 1 { - return nil, fmt.Errorf("unable to parse docker host `%s`", host) - } - - var basePath string - proto, addr := protoAddrParts[0], protoAddrParts[1] - if proto == "tcp" { - parsed, err := url.Parse("tcp://" + addr) - if err != nil { - return nil, err - } - addr = parsed.Host - basePath = parsed.Path - } - return &url.URL{ - Scheme: proto, - Host: addr, - Path: basePath, - }, nil -} - -// CustomHTTPHeaders returns the custom http headers stored by the client. -func (cli *Client) CustomHTTPHeaders() map[string]string { - m := make(map[string]string) - for k, v := range cli.customHTTPHeaders { - m[k] = v - } - return m -} - -// SetCustomHTTPHeaders that will be set on every HTTP request made by the client. -// Deprecated: use WithHTTPHeaders when creating the client. -func (cli *Client) SetCustomHTTPHeaders(headers map[string]string) { - cli.customHTTPHeaders = headers -} - -// Dialer returns a dialer for a raw stream connection, with HTTP/1.1 header, that can be used for proxying the daemon connection. -// Used by `docker dial-stdio` (docker/cli#889). -func (cli *Client) Dialer() func(context.Context) (net.Conn, error) { - return func(ctx context.Context) (net.Conn, error) { - if transport, ok := cli.client.Transport.(*http.Transport); ok { - if transport.DialContext != nil && transport.TLSClientConfig == nil { - return transport.DialContext(ctx, cli.proto, cli.addr) - } - } - return fallbackDial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport)) - } -} diff --git a/vendor/github.com/docker/docker/client/client_deprecated.go b/vendor/github.com/docker/docker/client/client_deprecated.go deleted file mode 100644 index 54cdfc29a84..00000000000 --- a/vendor/github.com/docker/docker/client/client_deprecated.go +++ /dev/null @@ -1,23 +0,0 @@ -package client - -import "net/http" - -// NewClient initializes a new API client for the given host and API version. -// It uses the given http client as transport. -// It also initializes the custom http headers to add to each request. -// -// It won't send any version information if the version number is empty. It is -// highly recommended that you set a version or your client may break if the -// server is upgraded. -// Deprecated: use NewClientWithOpts -func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) { - return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders)) -} - -// NewEnvClient initializes a new API client based on environment variables. -// See FromEnv for a list of support environment variables. -// -// Deprecated: use NewClientWithOpts(FromEnv) -func NewEnvClient() (*Client, error) { - return NewClientWithOpts(FromEnv) -} diff --git a/vendor/github.com/docker/docker/client/client_unix.go b/vendor/github.com/docker/docker/client/client_unix.go deleted file mode 100644 index 9d0f0dcbf0b..00000000000 --- a/vendor/github.com/docker/docker/client/client_unix.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build linux freebsd openbsd netbsd darwin solaris illumos dragonfly - -package client // import "github.com/docker/docker/client" - -// DefaultDockerHost defines os specific default if DOCKER_HOST is unset -const DefaultDockerHost = "unix:///var/run/docker.sock" - -const defaultProto = "unix" -const defaultAddr = "/var/run/docker.sock" diff --git a/vendor/github.com/docker/docker/client/client_windows.go b/vendor/github.com/docker/docker/client/client_windows.go deleted file mode 100644 index c649e54412c..00000000000 --- a/vendor/github.com/docker/docker/client/client_windows.go +++ /dev/null @@ -1,7 +0,0 @@ -package client // import "github.com/docker/docker/client" - -// DefaultDockerHost defines os specific default if DOCKER_HOST is unset -const DefaultDockerHost = "npipe:////./pipe/docker_engine" - -const defaultProto = "npipe" -const defaultAddr = "//./pipe/docker_engine" diff --git a/vendor/github.com/docker/docker/client/config_create.go b/vendor/github.com/docker/docker/client/config_create.go deleted file mode 100644 index ee7d411df06..00000000000 --- a/vendor/github.com/docker/docker/client/config_create.go +++ /dev/null @@ -1,25 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" -) - -// ConfigCreate creates a new Config. -func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) { - var response types.ConfigCreateResponse - if err := cli.NewVersionError("1.30", "config create"); err != nil { - return response, err - } - resp, err := cli.post(ctx, "/configs/create", nil, config, nil) - defer ensureReaderClosed(resp) - if err != nil { - return response, err - } - - 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 deleted file mode 100644 index 7d0ce3e11c0..00000000000 --- a/vendor/github.com/docker/docker/client/config_inspect.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/swarm" -) - -// 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} - } - if err := cli.NewVersionError("1.30", "config inspect"); err != nil { - return swarm.Config{}, nil, err - } - resp, err := cli.get(ctx, "/configs/"+id, nil, nil) - defer ensureReaderClosed(resp) - if err != nil { - return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id) - } - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return swarm.Config{}, nil, err - } - - var config swarm.Config - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&config) - - return config, body, err -} diff --git a/vendor/github.com/docker/docker/client/config_list.go b/vendor/github.com/docker/docker/client/config_list.go deleted file mode 100644 index 565acc6e273..00000000000 --- a/vendor/github.com/docker/docker/client/config_list.go +++ /dev/null @@ -1,38 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" -) - -// ConfigList returns the list of configs. -func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) { - if err := cli.NewVersionError("1.30", "config list"); err != nil { - return nil, err - } - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/configs", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return nil, err - } - - var configs []swarm.Config - 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 deleted file mode 100644 index a708fcaecfd..00000000000 --- a/vendor/github.com/docker/docker/client/config_remove.go +++ /dev/null @@ -1,13 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "context" - -// ConfigRemove removes a Config. -func (cli *Client) ConfigRemove(ctx context.Context, id string) error { - if err := cli.NewVersionError("1.30", "config remove"); err != nil { - return err - } - resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) - defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "config", id) -} diff --git a/vendor/github.com/docker/docker/client/config_update.go b/vendor/github.com/docker/docker/client/config_update.go deleted file mode 100644 index 39e59cf8589..00000000000 --- a/vendor/github.com/docker/docker/client/config_update.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - "strconv" - - "github.com/docker/docker/api/types/swarm" -) - -// ConfigUpdate attempts to update a Config -func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error { - if err := cli.NewVersionError("1.30", "config update"); err != nil { - return err - } - query := url.Values{} - query.Set("version", strconv.FormatUint(version.Index, 10)) - resp, err := cli.post(ctx, "/configs/"+id+"/update", query, config, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_attach.go b/vendor/github.com/docker/docker/client/container_attach.go deleted file mode 100644 index 88ba1ef6396..00000000000 --- a/vendor/github.com/docker/docker/client/container_attach.go +++ /dev/null @@ -1,57 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types" -) - -// ContainerAttach attaches a connection to a container in the server. -// It returns a types.HijackedConnection with the hijacked connection -// and the a reader to get output. It's up to the called to close -// the hijacked connection by calling types.HijackedResponse.Close. -// -// The stream format on the response will be in one of two formats: -// -// If the container is using a TTY, there is only a single stream (stdout), and -// data is copied directly from the container output stream, no extra -// multiplexing or headers. -// -// If the container is *not* using a TTY, streams for stdout and stderr are -// multiplexed. -// The format of the multiplexed stream is as follows: -// -// [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT} -// -// STREAM_TYPE can be 1 for stdout and 2 for stderr -// -// SIZE1, SIZE2, SIZE3, and SIZE4 are four bytes of uint32 encoded as big endian. -// This is the size of OUTPUT. -// -// You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this -// stream. -func (cli *Client) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) { - query := url.Values{} - if options.Stream { - query.Set("stream", "1") - } - if options.Stdin { - query.Set("stdin", "1") - } - if options.Stdout { - query.Set("stdout", "1") - } - if options.Stderr { - query.Set("stderr", "1") - } - if options.DetachKeys != "" { - query.Set("detachKeys", options.DetachKeys) - } - if options.Logs { - query.Set("logs", "1") - } - - headers := map[string][]string{"Content-Type": {"text/plain"}} - return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, headers) -} diff --git a/vendor/github.com/docker/docker/client/container_commit.go b/vendor/github.com/docker/docker/client/container_commit.go deleted file mode 100644 index 2966e88c8ec..00000000000 --- a/vendor/github.com/docker/docker/client/container_commit.go +++ /dev/null @@ -1,55 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "errors" - "net/url" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" -) - -// ContainerCommit applies changes into a container and creates a new tagged image. -func (cli *Client) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error) { - var repository, tag string - if options.Reference != "" { - ref, err := reference.ParseNormalizedNamed(options.Reference) - if err != nil { - return types.IDResponse{}, err - } - - if _, isCanonical := ref.(reference.Canonical); isCanonical { - return types.IDResponse{}, errors.New("refusing to create a tag with a digest reference") - } - ref = reference.TagNameOnly(ref) - - if tagged, ok := ref.(reference.Tagged); ok { - tag = tagged.Tag() - } - repository = reference.FamiliarName(ref) - } - - query := url.Values{} - query.Set("container", container) - query.Set("repo", repository) - query.Set("tag", tag) - query.Set("comment", options.Comment) - query.Set("author", options.Author) - for _, change := range options.Changes { - query.Add("changes", change) - } - if !options.Pause { - query.Set("pause", "0") - } - - var response types.IDResponse - 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) - 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 deleted file mode 100644 index bb278bf7f32..00000000000 --- a/vendor/github.com/docker/docker/client/container_copy.go +++ /dev/null @@ -1,103 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "path/filepath" - "strings" - - "github.com/docker/docker/api/types" -) - -// ContainerStatPath returns Stat information about a path inside the container filesystem. -func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path string) (types.ContainerPathStat, error) { - 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) - if err != nil { - return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path) - } - return getContainerPathStatFromHeader(response.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 types.CopyToContainerOptions) error { - 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. - if !options.AllowOverwriteDirWithFile { - query.Set("noOverwriteDirNonDir", "true") - } - - if options.CopyUIDGID { - query.Set("copyUIDGID", "true") - } - - apiPath := "/containers/" + containerID + "/archive" - - response, err := cli.putRaw(ctx, apiPath, query, content, nil) - defer ensureReaderClosed(response) - if err != nil { - return wrapResponseError(err, response, "container:path", containerID+":"+dstPath) - } - - // TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior - if response.statusCode != http.StatusOK { - return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) - } - - return nil -} - -// 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, types.ContainerPathStat, error) { - 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) - if err != nil { - return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath) - } - - // TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior - if response.statusCode != http.StatusOK { - return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) - } - - // In order to get the copy behavior right, we need to know information - // about both the source and the destination. The response headers include - // stat info about the source that we can use in deciding exactly how to - // 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) - if err != nil { - return nil, stat, fmt.Errorf("unable to get resource stat from response: %s", err) - } - return response.body, stat, err -} - -func getContainerPathStatFromHeader(header http.Header) (types.ContainerPathStat, error) { - var stat types.ContainerPathStat - - encodedStat := header.Get("X-Docker-Container-Path-Stat") - statDecoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(encodedStat)) - - err := json.NewDecoder(statDecoder).Decode(&stat) - if err != nil { - err = fmt.Errorf("unable to decode container path stat header: %s", err) - } - - return stat, err -} diff --git a/vendor/github.com/docker/docker/client/container_create.go b/vendor/github.com/docker/docker/client/container_create.go deleted file mode 100644 index b1d5fea5bd5..00000000000 --- a/vendor/github.com/docker/docker/client/container_create.go +++ /dev/null @@ -1,63 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/containerd/containerd/platforms" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/versions" - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - -type configWrapper struct { - *container.Config - HostConfig *container.HostConfig - NetworkingConfig *network.NetworkingConfig - Platform *specs.Platform -} - -// ContainerCreate creates a new container based in 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 *specs.Platform, containerName string) (container.ContainerCreateCreatedBody, error) { - var response container.ContainerCreateCreatedBody - - if err := cli.NewVersionError("1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil { - return response, err - } - - // When using API 1.24 and under, the client is responsible for removing the container - if hostConfig != nil && versions.LessThan(cli.ClientVersion(), "1.25") { - hostConfig.AutoRemove = false - } - - if err := cli.NewVersionError("1.41", "specify container image platform"); platform != nil && err != nil { - return response, err - } - - query := url.Values{} - if platform != nil { - query.Set("platform", platforms.Format(*platform)) - } - - if containerName != "" { - query.Set("name", containerName) - } - - body := configWrapper{ - Config: config, - HostConfig: hostConfig, - NetworkingConfig: networkingConfig, - } - - serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return response, err - } - - err = json.NewDecoder(serverResp.body).Decode(&response) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/container_diff.go b/vendor/github.com/docker/docker/client/container_diff.go deleted file mode 100644 index 29dac8491df..00000000000 --- a/vendor/github.com/docker/docker/client/container_diff.go +++ /dev/null @@ -1,23 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types/container" -) - -// ContainerDiff shows differences in a container filesystem since it was started. -func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.ContainerChangeResponseItem, error) { - var changes []container.ContainerChangeResponseItem - - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return changes, err - } - - err = json.NewDecoder(serverResp.body).Decode(&changes) - 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 deleted file mode 100644 index e3ee755b71d..00000000000 --- a/vendor/github.com/docker/docker/client/container_exec.go +++ /dev/null @@ -1,54 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types" -) - -// ContainerExecCreate creates a new exec configuration to run an exec process. -func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) { - var response types.IDResponse - - if err := cli.NewVersionError("1.25", "env"); len(config.Env) != 0 && err != nil { - return response, err - } - - resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil) - defer ensureReaderClosed(resp) - if err != nil { - return response, err - } - err = json.NewDecoder(resp.body).Decode(&response) - return response, err -} - -// ContainerExecStart starts an exec process already created in the docker host. -func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error { - resp, err := cli.post(ctx, "/exec/"+execID+"/start", nil, config, nil) - ensureReaderClosed(resp) - return err -} - -// ContainerExecAttach attaches a connection to an exec process in the server. -// It returns a types.HijackedConnection with the hijacked connection -// and the a reader to get output. It's up to the called to close -// the hijacked connection by calling types.HijackedResponse.Close. -func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) { - headers := map[string][]string{"Content-Type": {"application/json"}} - return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers) -} - -// ContainerExecInspect returns information about a specific exec process on the docker host. -func (cli *Client) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) { - var response types.ContainerExecInspect - resp, err := cli.get(ctx, "/exec/"+execID+"/json", nil, nil) - if err != nil { - return response, err - } - - 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 deleted file mode 100644 index d0c0a5cbadf..00000000000 --- a/vendor/github.com/docker/docker/client/container_export.go +++ /dev/null @@ -1,19 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" -) - -// ContainerExport retrieves the raw contents of a container -// 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) - if err != nil { - return nil, err - } - - return serverResp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/container_inspect.go b/vendor/github.com/docker/docker/client/container_inspect.go deleted file mode 100644 index c496bcffea5..00000000000 --- a/vendor/github.com/docker/docker/client/container_inspect.go +++ /dev/null @@ -1,53 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - "net/url" - - "github.com/docker/docker/api/types" -) - -// 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} - } - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID) - } - - var response types.ContainerJSON - err = json.NewDecoder(serverResp.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} - } - query := url.Values{} - if getSize { - query.Set("size", "1") - } - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID) - } - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return types.ContainerJSON{}, nil, err - } - - var response types.ContainerJSON - 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 deleted file mode 100644 index 4d6f1d23da9..00000000000 --- a/vendor/github.com/docker/docker/client/container_kill.go +++ /dev/null @@ -1,16 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" -) - -// 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 { - query := url.Values{} - query.Set("signal", signal) - - resp, err := cli.post(ctx, "/containers/"+containerID+"/kill", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_list.go b/vendor/github.com/docker/docker/client/container_list.go deleted file mode 100644 index a973de597fd..00000000000 --- a/vendor/github.com/docker/docker/client/container_list.go +++ /dev/null @@ -1,57 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - "strconv" - - "github.com/docker/docker/api/types" - "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 types.ContainerListOptions) ([]types.Container, error) { - query := url.Values{} - - if options.All { - query.Set("all", "1") - } - - if options.Limit != -1 { - query.Set("limit", strconv.Itoa(options.Limit)) - } - - if options.Since != "" { - query.Set("since", options.Since) - } - - if options.Before != "" { - query.Set("before", options.Before) - } - - if options.Size { - query.Set("size", "1") - } - - if options.Filters.Len() > 0 { - //nolint:staticcheck // ignore SA1019 for old code - filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters) - - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/containers/json", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return nil, err - } - - var containers []types.Container - 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 deleted file mode 100644 index 5b6541f0359..00000000000 --- a/vendor/github.com/docker/docker/client/container_logs.go +++ /dev/null @@ -1,80 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" - "time" - - "github.com/docker/docker/api/types" - timetypes "github.com/docker/docker/api/types/time" - "github.com/pkg/errors" -) - -// ContainerLogs returns the logs generated by a container in an io.ReadCloser. -// It's up to the caller to close the stream. -// -// The stream format on the response will be in one of two formats: -// -// If the container is using a TTY, there is only a single stream (stdout), and -// data is copied directly from the container output stream, no extra -// multiplexing or headers. -// -// If the container is *not* using a TTY, streams for stdout and stderr are -// multiplexed. -// The format of the multiplexed stream is as follows: -// -// [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT} -// -// STREAM_TYPE can be 1 for stdout and 2 for stderr -// -// SIZE1, SIZE2, SIZE3, and SIZE4 are four bytes of uint32 encoded as big endian. -// This is the size of OUTPUT. -// -// You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this -// stream. -func (cli *Client) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) { - query := url.Values{} - if options.ShowStdout { - query.Set("stdout", "1") - } - - if options.ShowStderr { - query.Set("stderr", "1") - } - - if options.Since != "" { - ts, err := timetypes.GetTimestamp(options.Since, time.Now()) - if err != nil { - return nil, errors.Wrap(err, `invalid value for "since"`) - } - query.Set("since", ts) - } - - if options.Until != "" { - ts, err := timetypes.GetTimestamp(options.Until, time.Now()) - if err != nil { - return nil, errors.Wrap(err, `invalid value for "until"`) - } - query.Set("until", ts) - } - - if options.Timestamps { - query.Set("timestamps", "1") - } - - if options.Details { - query.Set("details", "1") - } - - if options.Follow { - query.Set("follow", "1") - } - query.Set("tail", options.Tail) - - resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) - if err != nil { - return nil, wrapResponseError(err, resp, "container", container) - } - 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 deleted file mode 100644 index 5e7271a371c..00000000000 --- a/vendor/github.com/docker/docker/client/container_pause.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "context" - -// ContainerPause pauses the main process of a given container without terminating it. -func (cli *Client) ContainerPause(ctx context.Context, containerID string) error { - 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 deleted file mode 100644 index 04383deaaff..00000000000 --- a/vendor/github.com/docker/docker/client/container_prune.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" -) - -// ContainersPrune requests the daemon to delete unused data -func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) { - var report types.ContainersPruneReport - - if err := cli.NewVersionError("1.25", "container prune"); err != nil { - return report, err - } - - query, err := getFiltersQuery(pruneFilters) - if err != nil { - return report, err - } - - serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return report, err - } - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, 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 deleted file mode 100644 index df81461b889..00000000000 --- a/vendor/github.com/docker/docker/client/container_remove.go +++ /dev/null @@ -1,27 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types" -) - -// ContainerRemove kills and removes a container from the docker host. -func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options types.ContainerRemoveOptions) error { - query := url.Values{} - if options.RemoveVolumes { - query.Set("v", "1") - } - if options.RemoveLinks { - query.Set("link", "1") - } - - if options.Force { - query.Set("force", "1") - } - - resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) - defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "container", containerID) -} diff --git a/vendor/github.com/docker/docker/client/container_rename.go b/vendor/github.com/docker/docker/client/container_rename.go deleted file mode 100644 index 240fdf552b4..00000000000 --- a/vendor/github.com/docker/docker/client/container_rename.go +++ /dev/null @@ -1,15 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" -) - -// ContainerRename changes the name of a given container. -func (cli *Client) ContainerRename(ctx context.Context, containerID, newContainerName string) error { - query := url.Values{} - query.Set("name", newContainerName) - resp, err := cli.post(ctx, "/containers/"+containerID+"/rename", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_resize.go b/vendor/github.com/docker/docker/client/container_resize.go deleted file mode 100644 index a9d4c0c79a0..00000000000 --- a/vendor/github.com/docker/docker/client/container_resize.go +++ /dev/null @@ -1,29 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - "strconv" - - "github.com/docker/docker/api/types" -) - -// ContainerResize changes the size of the tty for a container. -func (cli *Client) ContainerResize(ctx context.Context, containerID string, options types.ResizeOptions) error { - 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 types.ResizeOptions) error { - return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width) -} - -func (cli *Client) resize(ctx context.Context, basePath string, height, width uint) error { - query := url.Values{} - query.Set("h", strconv.Itoa(int(height))) - query.Set("w", strconv.Itoa(int(width))) - - resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_restart.go b/vendor/github.com/docker/docker/client/container_restart.go deleted file mode 100644 index 41e421969f4..00000000000 --- a/vendor/github.com/docker/docker/client/container_restart.go +++ /dev/null @@ -1,22 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - "time" - - timetypes "github.com/docker/docker/api/types/time" -) - -// ContainerRestart stops and starts a container again. -// It makes the daemon to 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, timeout *time.Duration) error { - query := url.Values{} - if timeout != nil { - query.Set("t", timetypes.DurationToSecondsString(*timeout)) - } - resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_start.go b/vendor/github.com/docker/docker/client/container_start.go deleted file mode 100644 index c2e0b15dca8..00000000000 --- a/vendor/github.com/docker/docker/client/container_start.go +++ /dev/null @@ -1,23 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types" -) - -// ContainerStart sends a request to the docker daemon to start a container. -func (cli *Client) ContainerStart(ctx context.Context, containerID string, options types.ContainerStartOptions) error { - query := url.Values{} - if len(options.CheckpointID) != 0 { - query.Set("checkpoint", options.CheckpointID) - } - if len(options.CheckpointDir) != 0 { - query.Set("checkpoint-dir", options.CheckpointDir) - } - - resp, err := cli.post(ctx, "/containers/"+containerID+"/start", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_stats.go b/vendor/github.com/docker/docker/client/container_stats.go deleted file mode 100644 index 0a6488dde82..00000000000 --- a/vendor/github.com/docker/docker/client/container_stats.go +++ /dev/null @@ -1,42 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types" -) - -// 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) (types.ContainerStats, error) { - query := url.Values{} - query.Set("stream", "0") - if stream { - query.Set("stream", "1") - } - - resp, err := cli.get(ctx, "/containers/"+containerID+"/stats", query, nil) - if err != nil { - return types.ContainerStats{}, err - } - - osType := getDockerOS(resp.header.Get("Server")) - return types.ContainerStats{Body: resp.body, OSType: osType}, err -} - -// 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) (types.ContainerStats, error) { - query := url.Values{} - query.Set("stream", "0") - query.Set("one-shot", "1") - - resp, err := cli.get(ctx, "/containers/"+containerID+"/stats", query, nil) - if err != nil { - return types.ContainerStats{}, err - } - - osType := getDockerOS(resp.header.Get("Server")) - return types.ContainerStats{Body: resp.body, OSType: osType}, err -} diff --git a/vendor/github.com/docker/docker/client/container_stop.go b/vendor/github.com/docker/docker/client/container_stop.go deleted file mode 100644 index 629d7ab64c8..00000000000 --- a/vendor/github.com/docker/docker/client/container_stop.go +++ /dev/null @@ -1,26 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - "time" - - timetypes "github.com/docker/docker/api/types/time" -) - -// ContainerStop stops a container. In case the container fails to stop -// gracefully within a time frame specified by the timeout argument, -// it is forcefully terminated (killed). -// -// If the timeout is nil, the container's StopTimeout value is used, if set, -// 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, timeout *time.Duration) error { - query := url.Values{} - if timeout != nil { - query.Set("t", timetypes.DurationToSecondsString(*timeout)) - } - resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/container_top.go b/vendor/github.com/docker/docker/client/container_top.go deleted file mode 100644 index a5b78999bf0..00000000000 --- a/vendor/github.com/docker/docker/client/container_top.go +++ /dev/null @@ -1,28 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - "strings" - - "github.com/docker/docker/api/types/container" -) - -// 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 - query := url.Values{} - if len(arguments) > 0 { - query.Set("ps_args", strings.Join(arguments, " ")) - } - - resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return response, err - } - - 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 deleted file mode 100644 index 1d8f873169b..00000000000 --- a/vendor/github.com/docker/docker/client/container_unpause.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "context" - -// ContainerUnpause resumes the process execution within a container -func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error { - 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 deleted file mode 100644 index 6917cf9fb36..00000000000 --- a/vendor/github.com/docker/docker/client/container_update.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types/container" -) - -// ContainerUpdate updates 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) - if err != nil { - return response, err - } - - err = json.NewDecoder(serverResp.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 deleted file mode 100644 index 6ab8c1da96a..00000000000 --- a/vendor/github.com/docker/docker/client/container_wait.go +++ /dev/null @@ -1,83 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/versions" -) - -// ContainerWait waits until the specified container is in a certain state -// indicated by the given condition, either "not-running" (default), -// "next-exit", or "removed". -// -// If this client's API version is before 1.30, condition is ignored and -// ContainerWait will return immediately with the two channels, as the server -// will wait as if the condition were "not-running". -// -// If this client's API version is at least 1.30, ContainerWait blocks until -// the request has been acknowledged by the server (with a response header), -// then returns two channels on which the caller can wait for the exit status -// of the container or an error if there was a problem either beginning the -// wait request or in getting the response. This allows the caller to -// synchronize ContainerWait with other calls, such as specifying a -// "next-exit" condition before issuing a ContainerStart request. -func (cli *Client) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error) { - if versions.LessThan(cli.ClientVersion(), "1.30") { - return cli.legacyContainerWait(ctx, containerID) - } - - resultC := make(chan container.ContainerWaitOKBody) - errC := make(chan error, 1) - - query := url.Values{} - query.Set("condition", string(condition)) - - resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", query, nil, nil) - if err != nil { - defer ensureReaderClosed(resp) - errC <- err - return resultC, errC - } - - go func() { - defer ensureReaderClosed(resp) - var res container.ContainerWaitOKBody - if err := json.NewDecoder(resp.body).Decode(&res); err != nil { - errC <- err - return - } - - resultC <- res - }() - - return resultC, errC -} - -// legacyContainerWait returns immediately and doesn't have an option to wait -// until the container is removed. -func (cli *Client) legacyContainerWait(ctx context.Context, containerID string) (<-chan container.ContainerWaitOKBody, <-chan error) { - resultC := make(chan container.ContainerWaitOKBody) - errC := make(chan error) - - go func() { - resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", nil, nil, nil) - if err != nil { - errC <- err - return - } - defer ensureReaderClosed(resp) - - var res container.ContainerWaitOKBody - if err := json.NewDecoder(resp.body).Decode(&res); err != nil { - errC <- err - return - } - - resultC <- res - }() - - return resultC, errC -} diff --git a/vendor/github.com/docker/docker/client/disk_usage.go b/vendor/github.com/docker/docker/client/disk_usage.go deleted file mode 100644 index 354cd36939a..00000000000 --- a/vendor/github.com/docker/docker/client/disk_usage.go +++ /dev/null @@ -1,26 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" -) - -// DiskUsage requests the current data usage from the daemon -func (cli *Client) DiskUsage(ctx context.Context) (types.DiskUsage, error) { - var du types.DiskUsage - - serverResp, err := cli.get(ctx, "/system/df", nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return du, err - } - - if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil { - return du, 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 deleted file mode 100644 index f4e3794cb4c..00000000000 --- a/vendor/github.com/docker/docker/client/distribution_inspect.go +++ /dev/null @@ -1,38 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - registrytypes "github.com/docker/docker/api/types/registry" -) - -// DistributionInspect returns the image digest with full Manifest -func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) { - // Contact the registry to retrieve digest and platform information - var distributionInspect registrytypes.DistributionInspect - if image == "" { - return distributionInspect, objectNotFoundError{object: "distribution", id: image} - } - - if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil { - return distributionInspect, err - } - var headers map[string][]string - - if encodedRegistryAuth != "" { - headers = map[string][]string{ - "X-Registry-Auth": {encodedRegistryAuth}, - } - } - - resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers) - defer ensureReaderClosed(resp) - if err != nil { - return distributionInspect, err - } - - 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 deleted file mode 100644 index 041bc8d49c4..00000000000 --- a/vendor/github.com/docker/docker/client/errors.go +++ /dev/null @@ -1,138 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "fmt" - "net/http" - - "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/errdefs" - "github.com/pkg/errors" -) - -// errConnectionFailed implements an error returned when connection failed. -type errConnectionFailed struct { - host string -} - -// Error returns a string representation of an errConnectionFailed -func (err errConnectionFailed) Error() string { - if err.host == "" { - return "Cannot connect to the Docker daemon. Is the docker daemon running on this host?" - } - return fmt.Sprintf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", err.host) -} - -// IsErrConnectionFailed returns true if the error is caused by connection failed. -func IsErrConnectionFailed(err error) bool { - return errors.As(err, &errConnectionFailed{}) -} - -// ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed. -func ErrorConnectionFailed(host string) error { - return errConnectionFailed{host: host} -} - -// Deprecated: use the errdefs.NotFound() interface instead. Kept for backward compatibility -type notFound interface { - error - NotFound() bool -} - -// IsErrNotFound returns true if the error is a NotFound error, which is returned -// by the API when some object is not found. -func IsErrNotFound(err error) bool { - var e notFound - if errors.As(err, &e) { - return true - } - return errdefs.IsNotFound(err) -} - -type objectNotFoundError struct { - object string - id string -} - -func (e objectNotFoundError) NotFound() {} - -func (e objectNotFoundError) Error() string { - return fmt.Sprintf("Error: No such %s: %s", e.object, e.id) -} - -func wrapResponseError(err error, resp serverResponse, object, id string) error { - switch { - case err == nil: - return nil - case resp.statusCode == http.StatusNotFound: - return objectNotFoundError{object: object, id: id} - case resp.statusCode == http.StatusNotImplemented: - return errdefs.NotImplemented(err) - default: - return err - } -} - -// unauthorizedError represents an authorization error in a remote registry. -type unauthorizedError struct { - cause error -} - -// Error returns a string representation of an unauthorizedError -func (u unauthorizedError) Error() string { - return u.cause.Error() -} - -// IsErrUnauthorized returns true if the error is caused -// when a remote registry authentication fails -func IsErrUnauthorized(err error) bool { - if _, ok := err.(unauthorizedError); ok { - return ok - } - return errdefs.IsUnauthorized(err) -} - -type pluginPermissionDenied struct { - name string -} - -func (e pluginPermissionDenied) Error() string { - return "Permission denied while installing plugin " + e.name -} - -// IsErrPluginPermissionDenied returns true if the error is caused -// when a user denies a plugin's permissions -func IsErrPluginPermissionDenied(err error) bool { - _, ok := err.(pluginPermissionDenied) - return ok -} - -type notImplementedError struct { - message string -} - -func (e notImplementedError) Error() string { - return e.message -} - -func (e notImplementedError) NotImplemented() bool { - return true -} - -// IsErrNotImplemented returns true if the error is a NotImplemented error. -// This is returned by the API when a requested feature has not been -// implemented. -func IsErrNotImplemented(err error) bool { - if _, ok := err.(notImplementedError); ok { - return ok - } - return errdefs.IsNotImplemented(err) -} - -// NewVersionError returns an error if the APIVersion required -// if less than the current supported version -func (cli *Client) NewVersionError(APIrequired, feature string) error { - if cli.version != "" && versions.LessThan(cli.version, APIrequired) { - return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version) - } - return nil -} diff --git a/vendor/github.com/docker/docker/client/events.go b/vendor/github.com/docker/docker/client/events.go deleted file mode 100644 index f0dc9d9e12f..00000000000 --- a/vendor/github.com/docker/docker/client/events.go +++ /dev/null @@ -1,102 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" - timetypes "github.com/docker/docker/api/types/time" -) - -// Events returns a stream of events in the daemon. It's up to the caller to close the stream -// by cancelling the context. Once the stream has been completely read an io.EOF error will -// be sent over the error channel. If an error is sent all processing will be stopped. It's up -// to the caller to reopen the stream in the event of an error by reinvoking this method. -func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) { - - messages := make(chan events.Message) - errs := make(chan error, 1) - - started := make(chan struct{}) - go func() { - defer close(errs) - - query, err := buildEventsQueryParams(cli.version, options) - if err != nil { - close(started) - errs <- err - return - } - - resp, err := cli.get(ctx, "/events", query, nil) - if err != nil { - close(started) - errs <- err - return - } - defer resp.body.Close() - - decoder := json.NewDecoder(resp.body) - - close(started) - for { - select { - case <-ctx.Done(): - errs <- ctx.Err() - return - default: - var event events.Message - if err := decoder.Decode(&event); err != nil { - errs <- err - return - } - - select { - case messages <- event: - case <-ctx.Done(): - errs <- ctx.Err() - return - } - } - } - }() - <-started - - return messages, errs -} - -func buildEventsQueryParams(cliVersion string, options types.EventsOptions) (url.Values, error) { - query := url.Values{} - ref := time.Now() - - if options.Since != "" { - ts, err := timetypes.GetTimestamp(options.Since, ref) - if err != nil { - return nil, err - } - query.Set("since", ts) - } - - if options.Until != "" { - ts, err := timetypes.GetTimestamp(options.Until, ref) - if err != nil { - return nil, err - } - query.Set("until", ts) - } - - if options.Filters.Len() > 0 { - //nolint:staticcheck // ignore SA1019 for old code - filterJSON, err := filters.ToParamWithVersion(cliVersion, options.Filters) - if err != nil { - return nil, err - } - query.Set("filters", filterJSON) - } - - return query, nil -} diff --git a/vendor/github.com/docker/docker/client/hijack.go b/vendor/github.com/docker/docker/client/hijack.go deleted file mode 100644 index e1dc49ef0f6..00000000000 --- a/vendor/github.com/docker/docker/client/hijack.go +++ /dev/null @@ -1,145 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bufio" - "context" - "crypto/tls" - "fmt" - "net" - "net/http" - "net/http/httputil" - "net/url" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/go-connections/sockets" - "github.com/pkg/errors" -) - -// postHijacked sends a POST request and hijacks the connection. -func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) { - bodyEncoded, err := encodeData(body) - if err != nil { - return types.HijackedResponse{}, err - } - - apiPath := cli.getAPIPath(ctx, path, query) - req, err := http.NewRequest(http.MethodPost, apiPath, bodyEncoded) - if err != nil { - return types.HijackedResponse{}, err - } - req = cli.addHeaders(req, headers) - - conn, err := cli.setupHijackConn(ctx, req, "tcp") - if err != nil { - return types.HijackedResponse{}, err - } - - return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err -} - -// DialHijack returns a hijacked connection with negotiated protocol proto. -func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) { - req, err := http.NewRequest(http.MethodPost, url, nil) - if err != nil { - return nil, err - } - req = cli.addHeaders(req, meta) - - return cli.setupHijackConn(ctx, req, proto) -} - -// fallbackDial is used when WithDialer() was not called. -// See cli.Dialer(). -func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { - if tlsConfig != nil && proto != "unix" && proto != "npipe" { - return tls.Dial(proto, addr, tlsConfig) - } - if proto == "npipe" { - return sockets.DialPipe(addr, 32*time.Second) - } - return net.Dial(proto, addr) -} - -func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto string) (net.Conn, error) { - req.Host = cli.addr - 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?") - } - - // When we set up a TCP connection for hijack, there could be long periods - // of inactivity (a long running command with no output) that in certain - // network setups may cause ECONNTIMEOUT, leaving the client in an unknown - // state. Setting TCP KeepAlive on the socket connection will prohibit - // ECONNTIMEOUT unless the socket connection truly is broken - if tcpConn, ok := conn.(*net.TCPConn); ok { - tcpConn.SetKeepAlive(true) - tcpConn.SetKeepAlivePeriod(30 * time.Second) - } - - clientconn := httputil.NewClientConn(conn, nil) - defer clientconn.Close() - - // Server hijacks the connection, error 'connection closed' expected - resp, err := clientconn.Do(req) - - //nolint:staticcheck // ignore SA1019 for connecting to old (pre go1.8) daemons - if err != httputil.ErrPersistEOF { - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusSwitchingProtocols { - resp.Body.Close() - return nil, fmt.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode) - } - } - - c, br := clientconn.Hijack() - if br.Buffered() > 0 { - // If there is buffered content, wrap the connection. We return an - // object that implements CloseWrite iff the underlying connection - // implements it. - if _, ok := c.(types.CloseWriter); ok { - c = &hijackedConnCloseWriter{&hijackedConn{c, br}} - } else { - c = &hijackedConn{c, br} - } - } else { - br.Reset(nil) - } - - return c, nil -} - -// hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case -// that a) there was already buffered data in the http layer when Hijack() was -// called, and b) the underlying net.Conn does *not* implement CloseWrite(). -// hijackedConn does not implement CloseWrite() either. -type hijackedConn struct { - net.Conn - r *bufio.Reader -} - -func (c *hijackedConn) Read(b []byte) (int, error) { - return c.r.Read(b) -} - -// hijackedConnCloseWriter is a hijackedConn which additionally implements -// CloseWrite(). It is returned by setupHijackConn in the case that a) there -// was already buffered data in the http layer when Hijack() was called, and b) -// the underlying net.Conn *does* implement CloseWrite(). -type hijackedConnCloseWriter struct { - *hijackedConn -} - -var _ types.CloseWriter = &hijackedConnCloseWriter{} - -func (c *hijackedConnCloseWriter) CloseWrite() error { - conn := c.Conn.(types.CloseWriter) - return conn.CloseWrite() -} diff --git a/vendor/github.com/docker/docker/client/image_build.go b/vendor/github.com/docker/docker/client/image_build.go deleted file mode 100644 index 8fcf995036f..00000000000 --- a/vendor/github.com/docker/docker/client/image_build.go +++ /dev/null @@ -1,146 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/base64" - "encoding/json" - "io" - "net/http" - "net/url" - "strconv" - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" -) - -// ImageBuild sends request to the daemon to build images. -// The Body in the response implement an io.ReadCloser and it's up to the caller to -// close it. -func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { - query, err := cli.imageBuildOptionsToQuery(options) - if err != nil { - return types.ImageBuildResponse{}, err - } - - headers := http.Header(make(map[string][]string)) - buf, err := json.Marshal(options.AuthConfigs) - if err != nil { - return types.ImageBuildResponse{}, err - } - 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) - if err != nil { - return types.ImageBuildResponse{}, err - } - - osType := getDockerOS(serverResp.header.Get("Server")) - - return types.ImageBuildResponse{ - Body: serverResp.body, - OSType: osType, - }, nil -} - -func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) { - query := url.Values{ - "t": options.Tags, - "securityopt": options.SecurityOpt, - "extrahosts": options.ExtraHosts, - } - if options.SuppressOutput { - query.Set("q", "1") - } - if options.RemoteContext != "" { - query.Set("remote", options.RemoteContext) - } - if options.NoCache { - query.Set("nocache", "1") - } - if options.Remove { - query.Set("rm", "1") - } else { - query.Set("rm", "0") - } - - if options.ForceRemove { - query.Set("forcerm", "1") - } - - if options.PullParent { - query.Set("pull", "1") - } - - if options.Squash { - if err := cli.NewVersionError("1.25", "squash"); err != nil { - return query, err - } - query.Set("squash", "1") - } - - if !container.Isolation.IsDefault(options.Isolation) { - 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 - } - query.Set("ulimits", string(ulimitsJSON)) - - buildArgsJSON, err := json.Marshal(options.BuildArgs) - if err != nil { - return query, err - } - query.Set("buildargs", string(buildArgsJSON)) - - labelsJSON, err := json.Marshal(options.Labels) - if err != nil { - return query, err - } - query.Set("labels", string(labelsJSON)) - - cacheFromJSON, err := json.Marshal(options.CacheFrom) - if err != nil { - return query, err - } - query.Set("cachefrom", string(cacheFromJSON)) - if options.SessionID != "" { - query.Set("session", options.SessionID) - } - if options.Platform != "" { - if err := cli.NewVersionError("1.32", "platform"); err != nil { - return query, err - } - query.Set("platform", strings.ToLower(options.Platform)) - } - if options.BuildID != "" { - query.Set("buildid", options.BuildID) - } - query.Set("version", string(options.Version)) - - if options.Outputs != nil { - outputsJSON, err := json.Marshal(options.Outputs) - if err != nil { - return query, err - } - query.Set("outputs", string(outputsJSON)) - } - return query, nil -} diff --git a/vendor/github.com/docker/docker/client/image_create.go b/vendor/github.com/docker/docker/client/image_create.go deleted file mode 100644 index 239380474e6..00000000000 --- a/vendor/github.com/docker/docker/client/image_create.go +++ /dev/null @@ -1,37 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" - "strings" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" -) - -// ImageCreate creates a new image based in the parent options. -// It returns the JSON content in the response body. -func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) { - ref, err := reference.ParseNormalizedNamed(parentReference) - if err != nil { - return nil, err - } - - query := url.Values{} - query.Set("fromImage", reference.FamiliarName(ref)) - query.Set("tag", getAPITagFromNamedRef(ref)) - if options.Platform != "" { - query.Set("platform", strings.ToLower(options.Platform)) - } - resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) - if err != nil { - return nil, err - } - return resp.body, nil -} - -func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.post(ctx, "/images/create", query, nil, headers) -} diff --git a/vendor/github.com/docker/docker/client/image_history.go b/vendor/github.com/docker/docker/client/image_history.go deleted file mode 100644 index b5bea10d8f6..00000000000 --- a/vendor/github.com/docker/docker/client/image_history.go +++ /dev/null @@ -1,22 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types/image" -) - -// 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) - if err != nil { - return history, err - } - - err = json.NewDecoder(serverResp.body).Decode(&history) - return history, err -} diff --git a/vendor/github.com/docker/docker/client/image_import.go b/vendor/github.com/docker/docker/client/image_import.go deleted file mode 100644 index d3336d4106a..00000000000 --- a/vendor/github.com/docker/docker/client/image_import.go +++ /dev/null @@ -1,40 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" - "strings" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" -) - -// ImageImport creates a new image based in the source options. -// It returns the JSON content in the response body. -func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) { - if ref != "" { - // Check if the given image name can be resolved - if _, err := reference.ParseNormalizedNamed(ref); err != nil { - return nil, err - } - } - - query := url.Values{} - query.Set("fromSrc", source.SourceName) - query.Set("repo", ref) - query.Set("tag", options.Tag) - query.Set("message", options.Message) - if options.Platform != "" { - query.Set("platform", strings.ToLower(options.Platform)) - } - for _, change := range options.Changes { - query.Add("changes", change) - } - - resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil) - if err != nil { - return nil, err - } - 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 deleted file mode 100644 index 1eb8dce0259..00000000000 --- a/vendor/github.com/docker/docker/client/image_inspect.go +++ /dev/null @@ -1,32 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types" -) - -// ImageInspectWithRaw returns the image information and its raw representation. -func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) { - if imageID == "" { - return types.ImageInspect{}, nil, 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, wrapResponseError(err, serverResp, "image", imageID) - } - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return types.ImageInspect{}, nil, err - } - - var response types.ImageInspect - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/image_list.go b/vendor/github.com/docker/docker/client/image_list.go deleted file mode 100644 index a4d7505094c..00000000000 --- a/vendor/github.com/docker/docker/client/image_list.go +++ /dev/null @@ -1,46 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/versions" -) - -// ImageList returns a list of images in the docker host. -func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) { - var images []types.ImageSummary - query := url.Values{} - - optionFilters := options.Filters - referenceFilters := optionFilters.Get("reference") - if versions.LessThan(cli.version, "1.25") && len(referenceFilters) > 0 { - query.Set("filter", referenceFilters[0]) - for _, filterValue := range referenceFilters { - optionFilters.Del("reference", filterValue) - } - } - if optionFilters.Len() > 0 { - //nolint:staticcheck // ignore SA1019 for old code - filterJSON, err := filters.ToParamWithVersion(cli.version, optionFilters) - if err != nil { - return images, err - } - query.Set("filters", filterJSON) - } - if options.All { - query.Set("all", "1") - } - - serverResp, err := cli.get(ctx, "/images/json", query, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return images, err - } - - err = json.NewDecoder(serverResp.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 deleted file mode 100644 index 91016e493c4..00000000000 --- a/vendor/github.com/docker/docker/client/image_load.go +++ /dev/null @@ -1,29 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" - - "github.com/docker/docker/api/types" -) - -// 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) (types.ImageLoadResponse, error) { - v := url.Values{} - v.Set("quiet", "0") - if quiet { - v.Set("quiet", "1") - } - headers := map[string][]string{"Content-Type": {"application/x-tar"}} - resp, err := cli.postRaw(ctx, "/images/load", v, input, headers) - if err != nil { - return types.ImageLoadResponse{}, err - } - return types.ImageLoadResponse{ - Body: resp.body, - JSON: resp.header.Get("Content-Type") == "application/json", - }, nil -} diff --git a/vendor/github.com/docker/docker/client/image_prune.go b/vendor/github.com/docker/docker/client/image_prune.go deleted file mode 100644 index 56af6d7f98f..00000000000 --- a/vendor/github.com/docker/docker/client/image_prune.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" -) - -// ImagesPrune requests the daemon to delete unused data -func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (types.ImagesPruneReport, error) { - var report types.ImagesPruneReport - - if err := cli.NewVersionError("1.25", "image prune"); err != nil { - return report, err - } - - query, err := getFiltersQuery(pruneFilters) - if err != nil { - return report, err - } - - serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return report, err - } - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, 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 deleted file mode 100644 index a23975591be..00000000000 --- a/vendor/github.com/docker/docker/client/image_pull.go +++ /dev/null @@ -1,64 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" - "strings" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/errdefs" -) - -// ImagePull requests the docker host to pull an image from a remote registry. -// It executes the privileged function if the operation is unauthorized -// and it tries one more time. -// It's up to the caller to handle the io.ReadCloser and close it properly. -// -// FIXME(vdemeester): there is currently used in a few way in docker/docker -// - if not in trusted content, ref is used to pass the whole reference, and tag is empty -// - if in trusted content, ref is used to pass the reference name, and tag for the digest -func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.ImagePullOptions) (io.ReadCloser, error) { - ref, err := reference.ParseNormalizedNamed(refStr) - if err != nil { - return nil, err - } - - query := url.Values{} - query.Set("fromImage", reference.FamiliarName(ref)) - if !options.All { - query.Set("tag", getAPITagFromNamedRef(ref)) - } - if options.Platform != "" { - query.Set("platform", strings.ToLower(options.Platform)) - } - - resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) - if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil { - newAuthHeader, privilegeErr := options.PrivilegeFunc() - if privilegeErr != nil { - return nil, privilegeErr - } - resp, err = cli.tryImageCreate(ctx, query, newAuthHeader) - } - if err != nil { - return nil, err - } - return resp.body, nil -} - -// getAPITagFromNamedRef returns a tag from the specified reference. -// This function is necessary as long as the docker "server" api expects -// digests to be sent as tags and makes a distinction between the name -// and tag/digest part of a reference. -func getAPITagFromNamedRef(ref reference.Named) string { - if digested, ok := ref.(reference.Digested); ok { - return digested.Digest().String() - } - ref = reference.TagNameOnly(ref) - if tagged, ok := ref.(reference.Tagged); ok { - return tagged.Tag() - } - return "" -} diff --git a/vendor/github.com/docker/docker/client/image_push.go b/vendor/github.com/docker/docker/client/image_push.go deleted file mode 100644 index 845580d4a4c..00000000000 --- a/vendor/github.com/docker/docker/client/image_push.go +++ /dev/null @@ -1,54 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "errors" - "io" - "net/url" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/errdefs" -) - -// ImagePush requests the docker host to push an image to a remote registry. -// It executes the privileged function if the operation is unauthorized -// and it tries one more time. -// It's up to the caller to handle the io.ReadCloser and close it properly. -func (cli *Client) ImagePush(ctx context.Context, image string, options types.ImagePushOptions) (io.ReadCloser, error) { - ref, err := reference.ParseNormalizedNamed(image) - if err != nil { - return nil, err - } - - if _, isCanonical := ref.(reference.Canonical); isCanonical { - return nil, errors.New("cannot push a digest reference") - } - - name := reference.FamiliarName(ref) - query := url.Values{} - if !options.All { - ref = reference.TagNameOnly(ref) - if tagged, ok := ref.(reference.Tagged); ok { - query.Set("tag", tagged.Tag()) - } - } - - resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth) - if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil { - newAuthHeader, privilegeErr := options.PrivilegeFunc() - if privilegeErr != nil { - return nil, privilegeErr - } - resp, err = cli.tryImagePush(ctx, name, query, newAuthHeader) - } - if err != nil { - return nil, err - } - return resp.body, nil -} - -func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers) -} diff --git a/vendor/github.com/docker/docker/client/image_remove.go b/vendor/github.com/docker/docker/client/image_remove.go deleted file mode 100644 index 84a41af0f2c..00000000000 --- a/vendor/github.com/docker/docker/client/image_remove.go +++ /dev/null @@ -1,31 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" -) - -// ImageRemove removes an image from the docker host. -func (cli *Client) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - query := url.Values{} - - if options.Force { - query.Set("force", "1") - } - if !options.PruneChildren { - query.Set("noprune", "1") - } - - var dels []types.ImageDeleteResponseItem - resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return dels, wrapResponseError(err, resp, "image", imageID) - } - - 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 deleted file mode 100644 index d1314e4b22f..00000000000 --- a/vendor/github.com/docker/docker/client/image_save.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" -) - -// 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) { - query := url.Values{ - "names": imageIDs, - } - - resp, err := cli.get(ctx, "/images/get", query, nil) - if err != nil { - return nil, err - } - return resp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/image_search.go b/vendor/github.com/docker/docker/client/image_search.go deleted file mode 100644 index 82955a74775..00000000000 --- a/vendor/github.com/docker/docker/client/image_search.go +++ /dev/null @@ -1,51 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/errdefs" -) - -// ImageSearch makes the docker host to search by a term in a remote registry. -// The list of results is not sorted in any fashion. -func (cli *Client) ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) { - var results []registry.SearchResult - query := url.Values{} - query.Set("term", term) - query.Set("limit", fmt.Sprintf("%d", options.Limit)) - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return results, err - } - query.Set("filters", filterJSON) - } - - resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth) - defer ensureReaderClosed(resp) - if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil { - newAuthHeader, privilegeErr := options.PrivilegeFunc() - if privilegeErr != nil { - return results, privilegeErr - } - resp, err = cli.tryImageSearch(ctx, query, newAuthHeader) - } - if err != nil { - return results, err - } - - err = json.NewDecoder(resp.body).Decode(&results) - return results, err -} - -func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.get(ctx, "/images/search", query, headers) -} diff --git a/vendor/github.com/docker/docker/client/image_tag.go b/vendor/github.com/docker/docker/client/image_tag.go deleted file mode 100644 index 5652bfc252b..00000000000 --- a/vendor/github.com/docker/docker/client/image_tag.go +++ /dev/null @@ -1,37 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/distribution/reference" - "github.com/pkg/errors" -) - -// ImageTag tags an image in the docker host -func (cli *Client) ImageTag(ctx context.Context, source, target string) error { - if _, err := reference.ParseAnyReference(source); err != nil { - return errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", source) - } - - ref, err := reference.ParseNormalizedNamed(target) - if err != nil { - return errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", target) - } - - if _, isCanonical := ref.(reference.Canonical); isCanonical { - return errors.New("refusing to create a tag with a digest reference") - } - - ref = reference.TagNameOnly(ref) - - query := url.Values{} - query.Set("repo", reference.FamiliarName(ref)) - if tagged, ok := ref.(reference.Tagged); ok { - query.Set("tag", tagged.Tag()) - } - - resp, err := cli.post(ctx, "/images/"+source+"/tag", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/info.go b/vendor/github.com/docker/docker/client/info.go deleted file mode 100644 index c856704e23f..00000000000 --- a/vendor/github.com/docker/docker/client/info.go +++ /dev/null @@ -1,26 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - - "github.com/docker/docker/api/types" -) - -// Info returns information about the docker server. -func (cli *Client) Info(ctx context.Context) (types.Info, error) { - var info types.Info - serverResp, err := cli.get(ctx, "/info", url.Values{}, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return info, err - } - - if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil { - return info, fmt.Errorf("Error reading remote info: %v", err) - } - - return info, nil -} diff --git a/vendor/github.com/docker/docker/client/interface.go b/vendor/github.com/docker/docker/client/interface.go deleted file mode 100644 index aabad4a9110..00000000000 --- a/vendor/github.com/docker/docker/client/interface.go +++ /dev/null @@ -1,201 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net" - "net/http" - "time" - - "github.com/docker/docker/api/types" - containertypes "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - networktypes "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/api/types/swarm" - volumetypes "github.com/docker/docker/api/types/volume" - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - -// CommonAPIClient is the common methods between stable and experimental versions of APIClient. -type CommonAPIClient interface { - ConfigAPIClient - ContainerAPIClient - DistributionAPIClient - ImageAPIClient - NodeAPIClient - NetworkAPIClient - PluginAPIClient - ServiceAPIClient - SwarmAPIClient - SecretAPIClient - SystemAPIClient - VolumeAPIClient - ClientVersion() string - DaemonHost() string - HTTPClient() *http.Client - 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) - Dialer() func(context.Context) (net.Conn, error) - Close() error -} - -// ContainerAPIClient defines API client methods for the containers -type ContainerAPIClient interface { - ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) - ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error) - ContainerCreate(ctx context.Context, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkingConfig *networktypes.NetworkingConfig, platform *specs.Platform, containerName string) (containertypes.ContainerCreateCreatedBody, error) - ContainerDiff(ctx context.Context, container string) ([]containertypes.ContainerChangeResponseItem, error) - ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) - ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) - ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) - ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error - ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) 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) - ContainerKill(ctx context.Context, container, signal string) error - ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) - ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) - ContainerPause(ctx context.Context, container string) error - ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error - ContainerRename(ctx context.Context, container, newContainerName string) error - ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error - ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error - ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error) - ContainerStats(ctx context.Context, container string, stream bool) (types.ContainerStats, error) - ContainerStatsOneShot(ctx context.Context, container string) (types.ContainerStats, error) - ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error - ContainerStop(ctx context.Context, container string, timeout *time.Duration) error - ContainerTop(ctx context.Context, container string, arguments []string) (containertypes.ContainerTopOKBody, error) - ContainerUnpause(ctx context.Context, container string) error - ContainerUpdate(ctx context.Context, container string, updateConfig containertypes.UpdateConfig) (containertypes.ContainerUpdateOKBody, error) - ContainerWait(ctx context.Context, container string, condition containertypes.WaitCondition) (<-chan containertypes.ContainerWaitOKBody, <-chan error) - CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) - CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error - ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) -} - -// DistributionAPIClient defines API client methods for the registry -type DistributionAPIClient interface { - DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registry.DistributionInspect, error) -} - -// ImageAPIClient defines API client methods for the images -type ImageAPIClient interface { - ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) - BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) - BuildCancel(ctx context.Context, id string) error - ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) - ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error) - ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) - ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error) - ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) - ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) - ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) - ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) - ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) - ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]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) (types.ImagesPruneReport, error) -} - -// NetworkAPIClient defines API client methods for the networks -type NetworkAPIClient interface { - NetworkConnect(ctx context.Context, network, container string, config *networktypes.EndpointSettings) error - NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) - NetworkDisconnect(ctx context.Context, network, container string, force bool) error - NetworkInspect(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, error) - NetworkInspectWithRaw(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error) - NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) - NetworkRemove(ctx context.Context, network string) error - NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error) -} - -// NodeAPIClient defines API client methods for the nodes -type NodeAPIClient interface { - NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) - NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) - NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error - NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error -} - -// PluginAPIClient defines API client methods for the plugins -type PluginAPIClient interface { - PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error) - PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error - PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error - PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error - PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error) - PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error) - PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) - PluginSet(ctx context.Context, name string, args []string) error - PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) - PluginCreate(ctx context.Context, createContext io.Reader, options types.PluginCreateOptions) error -} - -// ServiceAPIClient defines API client methods for the services -type ServiceAPIClient interface { - ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) - ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) - ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) - ServiceRemove(ctx context.Context, serviceID string) error - ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) - ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error) - TaskLogs(ctx context.Context, taskID string, options types.ContainerLogsOptions) (io.ReadCloser, error) - TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) - TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) -} - -// SwarmAPIClient defines API client methods for the swarm -type SwarmAPIClient interface { - SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) - SwarmJoin(ctx context.Context, req swarm.JoinRequest) error - SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) - SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error - SwarmLeave(ctx context.Context, force bool) error - SwarmInspect(ctx context.Context) (swarm.Swarm, error) - SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error -} - -// SystemAPIClient defines API client methods for the system -type SystemAPIClient interface { - Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) - Info(ctx context.Context) (types.Info, error) - RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) - DiskUsage(ctx context.Context) (types.DiskUsage, error) - Ping(ctx context.Context) (types.Ping, error) -} - -// VolumeAPIClient defines API client methods for the volumes -type VolumeAPIClient interface { - VolumeCreate(ctx context.Context, options volumetypes.VolumeCreateBody) (types.Volume, error) - VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) - VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error) - VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumeListOKBody, error) - VolumeRemove(ctx context.Context, volumeID string, force bool) error - VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error) -} - -// SecretAPIClient defines API client methods for secrets -type SecretAPIClient interface { - SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) - SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) - SecretRemove(ctx context.Context, id string) error - SecretInspectWithRaw(ctx context.Context, name string) (swarm.Secret, []byte, error) - SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error -} - -// ConfigAPIClient defines API client methods for configs -type ConfigAPIClient interface { - ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) - ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) - ConfigRemove(ctx context.Context, id string) error - ConfigInspectWithRaw(ctx context.Context, name string) (swarm.Config, []byte, error) - ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error -} diff --git a/vendor/github.com/docker/docker/client/interface_experimental.go b/vendor/github.com/docker/docker/client/interface_experimental.go deleted file mode 100644 index 402ffb512cd..00000000000 --- a/vendor/github.com/docker/docker/client/interface_experimental.go +++ /dev/null @@ -1,18 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - - "github.com/docker/docker/api/types" -) - -type apiClientExperimental interface { - CheckpointAPIClient -} - -// CheckpointAPIClient defines API client methods for the checkpoints -type CheckpointAPIClient interface { - CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error - CheckpointDelete(ctx context.Context, container string, options types.CheckpointDeleteOptions) error - CheckpointList(ctx context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) -} 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 5502cd74266..00000000000 --- 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 deleted file mode 100644 index f0585206382..00000000000 --- a/vendor/github.com/docker/docker/client/login.go +++ /dev/null @@ -1,25 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/registry" -) - -// RegistryLogin authenticates the docker server with a given docker registry. -// It returns unauthorizedError when the authentication fails. -func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) { - resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil) - defer ensureReaderClosed(resp) - - if err != nil { - return registry.AuthenticateOKBody{}, err - } - - var response registry.AuthenticateOKBody - 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 deleted file mode 100644 index 57189461341..00000000000 --- a/vendor/github.com/docker/docker/client/network_connect.go +++ /dev/null @@ -1,19 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/network" -) - -// 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 { - nc := types.NetworkConnect{ - Container: containerID, - EndpointConfig: config, - } - resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/network_create.go b/vendor/github.com/docker/docker/client/network_create.go deleted file mode 100644 index 278d9383a86..00000000000 --- a/vendor/github.com/docker/docker/client/network_create.go +++ /dev/null @@ -1,25 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types" -) - -// NetworkCreate creates a new network in the docker host. -func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) { - networkCreateRequest := types.NetworkCreateRequest{ - NetworkCreate: options, - Name: name, - } - var response types.NetworkCreateResponse - serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return response, err - } - - err = json.NewDecoder(serverResp.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 deleted file mode 100644 index dd156766566..00000000000 --- a/vendor/github.com/docker/docker/client/network_disconnect.go +++ /dev/null @@ -1,15 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - - "github.com/docker/docker/api/types" -) - -// 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 { - nd := types.NetworkDisconnect{Container: containerID, Force: force} - resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, nd, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/network_inspect.go b/vendor/github.com/docker/docker/client/network_inspect.go deleted file mode 100644 index 89a05b3021a..00000000000 --- a/vendor/github.com/docker/docker/client/network_inspect.go +++ /dev/null @@ -1,49 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - "net/url" - - "github.com/docker/docker/api/types" -) - -// NetworkInspect returns the information for a specific network configured in the docker host. -func (cli *Client) NetworkInspect(ctx context.Context, networkID string, options types.NetworkInspectOptions) (types.NetworkResource, error) { - networkResource, _, err := cli.NetworkInspectWithRaw(ctx, networkID, options) - return networkResource, err -} - -// 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 types.NetworkInspectOptions) (types.NetworkResource, []byte, error) { - if networkID == "" { - return types.NetworkResource{}, nil, objectNotFoundError{object: "network", id: networkID} - } - var ( - networkResource types.NetworkResource - resp serverResponse - err error - ) - query := url.Values{} - if options.Verbose { - query.Set("verbose", "true") - } - if options.Scope != "" { - query.Set("scope", options.Scope) - } - resp, err = cli.get(ctx, "/networks/"+networkID, query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return networkResource, nil, wrapResponseError(err, resp, "network", networkID) - } - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return networkResource, nil, err - } - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&networkResource) - return networkResource, body, err -} diff --git a/vendor/github.com/docker/docker/client/network_list.go b/vendor/github.com/docker/docker/client/network_list.go deleted file mode 100644 index ed2acb55711..00000000000 --- a/vendor/github.com/docker/docker/client/network_list.go +++ /dev/null @@ -1,32 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" -) - -// NetworkList returns the list of networks configured in the docker host. -func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) { - 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 nil, err - } - - query.Set("filters", filterJSON) - } - var networkResources []types.NetworkResource - resp, err := cli.get(ctx, "/networks", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return networkResources, err - } - 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 deleted file mode 100644 index cebb1882192..00000000000 --- a/vendor/github.com/docker/docker/client/network_prune.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" -) - -// NetworksPrune requests the daemon to delete unused networks -func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (types.NetworksPruneReport, error) { - var report types.NetworksPruneReport - - if err := cli.NewVersionError("1.25", "network prune"); err != nil { - return report, err - } - - query, err := getFiltersQuery(pruneFilters) - if err != nil { - return report, err - } - - serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return report, err - } - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, 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 deleted file mode 100644 index e71b16d8692..00000000000 --- a/vendor/github.com/docker/docker/client/network_remove.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "context" - -// NetworkRemove removes an existent network from the docker host. -func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { - resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) - defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "network", networkID) -} diff --git a/vendor/github.com/docker/docker/client/node_inspect.go b/vendor/github.com/docker/docker/client/node_inspect.go deleted file mode 100644 index d296c9fdde3..00000000000 --- a/vendor/github.com/docker/docker/client/node_inspect.go +++ /dev/null @@ -1,32 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/swarm" -) - -// 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} - } - serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID) - } - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return swarm.Node{}, nil, err - } - - var response swarm.Node - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/node_list.go b/vendor/github.com/docker/docker/client/node_list.go deleted file mode 100644 index c212906bc71..00000000000 --- a/vendor/github.com/docker/docker/client/node_list.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" -) - -// NodeList returns the list of nodes. -func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) { - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/nodes", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return nil, err - } - - var nodes []swarm.Node - 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 deleted file mode 100644 index 03ab8780974..00000000000 --- a/vendor/github.com/docker/docker/client/node_remove.go +++ /dev/null @@ -1,20 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types" -) - -// NodeRemove removes a Node. -func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error { - query := url.Values{} - if options.Force { - query.Set("force", "1") - } - - resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil) - defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "node", nodeID) -} diff --git a/vendor/github.com/docker/docker/client/node_update.go b/vendor/github.com/docker/docker/client/node_update.go deleted file mode 100644 index de32a617fb0..00000000000 --- a/vendor/github.com/docker/docker/client/node_update.go +++ /dev/null @@ -1,18 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - "strconv" - - "github.com/docker/docker/api/types/swarm" -) - -// NodeUpdate updates a Node. -func (cli *Client) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error { - query := url.Values{} - query.Set("version", strconv.FormatUint(version.Index, 10)) - resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, node, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/options.go b/vendor/github.com/docker/docker/client/options.go deleted file mode 100644 index 6f77f0955f6..00000000000 --- a/vendor/github.com/docker/docker/client/options.go +++ /dev/null @@ -1,172 +0,0 @@ -package client - -import ( - "context" - "net" - "net/http" - "os" - "path/filepath" - "time" - - "github.com/docker/go-connections/sockets" - "github.com/docker/go-connections/tlsconfig" - "github.com/pkg/errors" -) - -// Opt is a configuration option to initialize a client -type Opt func(*Client) error - -// FromEnv configures the client with values from environment variables. -// -// Supported environment variables: -// DOCKER_HOST to set the url to the docker server. -// DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest. -// DOCKER_CERT_PATH to load the TLS certificates from. -// DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default. -func FromEnv(c *Client) error { - if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" { - options := tlsconfig.Options{ - CAFile: filepath.Join(dockerCertPath, "ca.pem"), - CertFile: filepath.Join(dockerCertPath, "cert.pem"), - KeyFile: filepath.Join(dockerCertPath, "key.pem"), - InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "", - } - tlsc, err := tlsconfig.Client(options) - if err != nil { - return err - } - - c.client = &http.Client{ - Transport: &http.Transport{TLSClientConfig: tlsc}, - CheckRedirect: CheckRedirect, - } - } - - if host := os.Getenv("DOCKER_HOST"); host != "" { - if err := WithHost(host)(c); err != nil { - return err - } - } - - if version := os.Getenv("DOCKER_API_VERSION"); version != "" { - if err := WithVersion(version)(c); err != nil { - return err - } - } - return nil -} - -// WithDialer applies the dialer.DialContext to the client transport. This can be -// used to set the Timeout and KeepAlive settings of the client. -// Deprecated: use WithDialContext -func WithDialer(dialer *net.Dialer) Opt { - return WithDialContext(dialer.DialContext) -} - -// WithDialContext applies the dialer to the client transport. This can be -// used to set the Timeout and KeepAlive settings of the client. -func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) Opt { - return func(c *Client) error { - if transport, ok := c.client.Transport.(*http.Transport); ok { - transport.DialContext = dialContext - return nil - } - return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport) - } -} - -// WithHost overrides the client host with the specified one. -func WithHost(host string) Opt { - return func(c *Client) error { - hostURL, err := ParseHostURL(host) - if err != nil { - return err - } - c.host = host - c.proto = hostURL.Scheme - c.addr = hostURL.Host - c.basePath = hostURL.Path - if transport, ok := c.client.Transport.(*http.Transport); ok { - return sockets.ConfigureTransport(transport, c.proto, c.addr) - } - return errors.Errorf("cannot apply host to transport: %T", c.client.Transport) - } -} - -// WithHTTPClient overrides the client http client with the specified one -func WithHTTPClient(client *http.Client) Opt { - return func(c *Client) error { - if client != nil { - c.client = client - } - return nil - } -} - -// WithTimeout configures the time limit for requests made by the HTTP client -func WithTimeout(timeout time.Duration) Opt { - return func(c *Client) error { - c.client.Timeout = timeout - return nil - } -} - -// WithHTTPHeaders overrides the client default http headers -func WithHTTPHeaders(headers map[string]string) Opt { - return func(c *Client) error { - c.customHTTPHeaders = headers - return nil - } -} - -// WithScheme overrides the client scheme with the specified one -func WithScheme(scheme string) Opt { - return func(c *Client) error { - c.scheme = scheme - return nil - } -} - -// WithTLSClientConfig applies a tls config to the client transport. -func WithTLSClientConfig(cacertPath, certPath, keyPath string) Opt { - return func(c *Client) error { - opts := tlsconfig.Options{ - CAFile: cacertPath, - CertFile: certPath, - KeyFile: keyPath, - ExclusiveRootPools: true, - } - config, err := tlsconfig.Client(opts) - if err != nil { - return errors.Wrap(err, "failed to create tls config") - } - if transport, ok := c.client.Transport.(*http.Transport); ok { - transport.TLSClientConfig = config - return nil - } - return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport) - } -} - -// WithVersion overrides the client version with the specified one. If an empty -// version is specified, the value will be ignored to allow version negotiation. -func WithVersion(version string) Opt { - return func(c *Client) error { - if version != "" { - c.version = version - c.manualOverride = true - } - return nil - } -} - -// WithAPIVersionNegotiation enables automatic API version negotiation for the client. -// With this option enabled, the client automatically negotiates the API version -// to use when making requests. API version negotiation is performed on the first -// request; subsequent requests will not re-negotiate. -func WithAPIVersionNegotiation() Opt { - return func(c *Client) error { - c.negotiateVersion = true - return nil - } -} diff --git a/vendor/github.com/docker/docker/client/ping.go b/vendor/github.com/docker/docker/client/ping.go deleted file mode 100644 index a9af001ef46..00000000000 --- a/vendor/github.com/docker/docker/client/ping.go +++ /dev/null @@ -1,66 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/http" - "path" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/errdefs" -) - -// Ping pings the server and returns the value of the "Docker-Experimental", -// "Builder-Version", "OS-Type" & "API-Version" headers. It attempts to use -// a HEAD request on the endpoint, but falls back to GET if HEAD is not supported -// by the daemon. -func (cli *Client) Ping(ctx context.Context) (types.Ping, error) { - var ping types.Ping - - // Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest() - // because ping requests are used during API version negotiation, so we want - // to hit the non-versioned /_ping endpoint, not /v1.xx/_ping - req, err := cli.buildRequest(http.MethodHead, path.Join(cli.basePath, "/_ping"), nil, nil) - if err != nil { - return ping, err - } - serverResp, err := cli.doRequest(ctx, req) - if err == nil { - defer ensureReaderClosed(serverResp) - switch serverResp.statusCode { - case http.StatusOK, http.StatusInternalServerError: - // Server handled the request, so parse the response - return parsePingResponse(cli, serverResp) - } - } else if IsErrConnectionFailed(err) { - return ping, err - } - - req, err = cli.buildRequest(http.MethodGet, path.Join(cli.basePath, "/_ping"), nil, nil) - if err != nil { - return ping, err - } - serverResp, err = cli.doRequest(ctx, req) - defer ensureReaderClosed(serverResp) - if err != nil { - return ping, err - } - return parsePingResponse(cli, serverResp) -} - -func parsePingResponse(cli *Client, resp serverResponse) (types.Ping, error) { - var ping types.Ping - if resp.header == nil { - err := cli.checkResponseErr(resp) - return ping, errdefs.FromStatusCode(err, resp.statusCode) - } - 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 != "" { - ping.BuilderVersion = types.BuilderVersion(bv) - } - err := cli.checkResponseErr(resp) - return ping, errdefs.FromStatusCode(err, resp.statusCode) -} diff --git a/vendor/github.com/docker/docker/client/plugin_create.go b/vendor/github.com/docker/docker/client/plugin_create.go deleted file mode 100644 index b95dbaf6863..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_create.go +++ /dev/null @@ -1,23 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/http" - "net/url" - - "github.com/docker/docker/api/types" -) - -// PluginCreate creates a plugin -func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, createOptions types.PluginCreateOptions) error { - headers := http.Header(make(map[string][]string)) - headers.Set("Content-Type", "application/x-tar") - - query := url.Values{} - query.Set("name", createOptions.RepoName) - - resp, err := cli.postRaw(ctx, "/plugins/create", query, createContext, headers) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/plugin_disable.go b/vendor/github.com/docker/docker/client/plugin_disable.go deleted file mode 100644 index 01f6574f952..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_disable.go +++ /dev/null @@ -1,19 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types" -) - -// PluginDisable disables a plugin -func (cli *Client) PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error { - query := url.Values{} - if options.Force { - query.Set("force", "1") - } - resp, err := cli.post(ctx, "/plugins/"+name+"/disable", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/plugin_enable.go b/vendor/github.com/docker/docker/client/plugin_enable.go deleted file mode 100644 index 736da48bd10..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_enable.go +++ /dev/null @@ -1,19 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - "strconv" - - "github.com/docker/docker/api/types" -) - -// PluginEnable enables a plugin -func (cli *Client) PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error { - query := url.Values{} - query.Set("timeout", strconv.Itoa(options.Timeout)) - - resp, err := cli.post(ctx, "/plugins/"+name+"/enable", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/plugin_inspect.go b/vendor/github.com/docker/docker/client/plugin_inspect.go deleted file mode 100644 index 81b89732b03..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_inspect.go +++ /dev/null @@ -1,31 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types" -) - -// 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} - } - resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) - defer ensureReaderClosed(resp) - if err != nil { - return nil, nil, wrapResponseError(err, resp, "plugin", name) - } - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return nil, nil, err - } - var p types.Plugin - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&p) - return &p, body, err -} diff --git a/vendor/github.com/docker/docker/client/plugin_install.go b/vendor/github.com/docker/docker/client/plugin_install.go deleted file mode 100644 index 012afe61cac..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_install.go +++ /dev/null @@ -1,113 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "io" - "net/url" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/errdefs" - "github.com/pkg/errors" -) - -// PluginInstall installs a plugin -func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) { - query := url.Values{} - if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil { - return nil, errors.Wrap(err, "invalid remote reference") - } - query.Set("remote", options.RemoteRef) - - privileges, err := cli.checkPluginPermissions(ctx, query, options) - if err != nil { - return nil, err - } - - // set name for plugin pull, if empty should default to remote reference - query.Set("name", name) - - resp, err := cli.tryPluginPull(ctx, query, privileges, options.RegistryAuth) - if err != nil { - return nil, err - } - - 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) - if err != nil { - pw.CloseWithError(err) - return - } - defer func() { - if err != nil { - delResp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil) - ensureReaderClosed(delResp) - } - }() - if len(options.Args) > 0 { - if err := cli.PluginSet(ctx, name, options.Args); err != nil { - pw.CloseWithError(err) - return - } - } - - if options.Disabled { - pw.Close() - return - } - - enableErr := cli.PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: 0}) - pw.CloseWithError(enableErr) - }() - return pr, nil -} - -func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.get(ctx, "/plugins/privileges", query, headers) -} - -func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges types.PluginPrivileges, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.post(ctx, "/plugins/pull", query, privileges, headers) -} - -func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options types.PluginInstallOptions) (types.PluginPrivileges, error) { - resp, err := cli.tryPluginPrivileges(ctx, query, options.RegistryAuth) - if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil { - // todo: do inspect before to check existing name before checking privileges - newAuthHeader, privilegeErr := options.PrivilegeFunc() - if privilegeErr != nil { - ensureReaderClosed(resp) - return nil, privilegeErr - } - options.RegistryAuth = newAuthHeader - resp, err = cli.tryPluginPrivileges(ctx, query, options.RegistryAuth) - } - if err != nil { - ensureReaderClosed(resp) - return nil, err - } - - var privileges types.PluginPrivileges - if err := json.NewDecoder(resp.body).Decode(&privileges); err != nil { - ensureReaderClosed(resp) - return nil, err - } - ensureReaderClosed(resp) - - if !options.AcceptAllPermissions && options.AcceptPermissionsFunc != nil && len(privileges) > 0 { - accept, err := options.AcceptPermissionsFunc(privileges) - if err != nil { - return nil, err - } - if !accept { - return nil, pluginPermissionDenied{options.RemoteRef} - } - } - return privileges, nil -} diff --git a/vendor/github.com/docker/docker/client/plugin_list.go b/vendor/github.com/docker/docker/client/plugin_list.go deleted file mode 100644 index cf1935e2f5e..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_list.go +++ /dev/null @@ -1,33 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" -) - -// PluginList returns the installed plugins -func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error) { - var plugins types.PluginsListResponse - query := url.Values{} - - if filter.Len() > 0 { - //nolint:staticcheck // ignore SA1019 for old code - filterJSON, err := filters.ToParamWithVersion(cli.version, filter) - if err != nil { - return plugins, err - } - query.Set("filters", filterJSON) - } - resp, err := cli.get(ctx, "/plugins", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return plugins, wrapResponseError(err, resp, "plugin", "") - } - - 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 deleted file mode 100644 index d20bfe84479..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_push.go +++ /dev/null @@ -1,16 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" -) - -// PluginPush pushes a plugin to a registry -func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, headers) - if err != nil { - return nil, err - } - 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 deleted file mode 100644 index 51ca1040d6d..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_remove.go +++ /dev/null @@ -1,20 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types" -) - -// PluginRemove removes a plugin -func (cli *Client) PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error { - query := url.Values{} - if options.Force { - query.Set("force", "1") - } - - resp, err := cli.delete(ctx, "/plugins/"+name, query, nil) - defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "plugin", name) -} diff --git a/vendor/github.com/docker/docker/client/plugin_set.go b/vendor/github.com/docker/docker/client/plugin_set.go deleted file mode 100644 index dcf5752ca2b..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_set.go +++ /dev/null @@ -1,12 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" -) - -// PluginSet modifies settings for an existing plugin -func (cli *Client) PluginSet(ctx context.Context, name string, args []string) error { - 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 deleted file mode 100644 index 115cea945ba..00000000000 --- a/vendor/github.com/docker/docker/client/plugin_upgrade.go +++ /dev/null @@ -1,39 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" -) - -// PluginUpgrade upgrades a plugin -func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) { - if err := cli.NewVersionError("1.26", "plugin upgrade"); err != nil { - return nil, err - } - query := url.Values{} - if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil { - return nil, errors.Wrap(err, "invalid remote reference") - } - query.Set("remote", options.RemoteRef) - - privileges, err := cli.checkPluginPermissions(ctx, query, options) - if err != nil { - return nil, err - } - - resp, err := cli.tryPluginUpgrade(ctx, query, privileges, name, options.RegistryAuth) - if err != nil { - return nil, err - } - return resp.body, nil -} - -func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges types.PluginPrivileges, name, registryAuth string) (serverResponse, error) { - headers := map[string][]string{"X-Registry-Auth": {registryAuth}} - return cli.post(ctx, "/plugins/"+name+"/upgrade", query, privileges, headers) -} diff --git a/vendor/github.com/docker/docker/client/request.go b/vendor/github.com/docker/docker/client/request.go deleted file mode 100644 index 813eac2c9e0..00000000000 --- a/vendor/github.com/docker/docker/client/request.go +++ /dev/null @@ -1,269 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "net/url" - "os" - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/errdefs" - "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 map[string][]string) (serverResponse, 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 map[string][]string) (serverResponse, 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 map[string][]string) (serverResponse, error) { - body, headers, err := encodeBody(obj, headers) - if err != nil { - return serverResponse{}, 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 map[string][]string) (serverResponse, error) { - return cli.sendRequest(ctx, http.MethodPost, 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 map[string][]string) (serverResponse, error) { - return cli.sendRequest(ctx, http.MethodPut, path, query, body, headers) -} - -// 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 map[string][]string) (serverResponse, error) { - return cli.sendRequest(ctx, http.MethodDelete, path, query, nil, headers) -} - -type headers map[string][]string - -func encodeBody(obj interface{}, headers headers) (io.Reader, headers, error) { - if obj == nil { - return nil, headers, nil - } - - body, err := encodeData(obj) - if err != nil { - return nil, headers, err - } - if headers == nil { - headers = make(map[string][]string) - } - headers["Content-Type"] = []string{"application/json"} - return body, headers, nil -} - -func (cli *Client) buildRequest(method, path string, body io.Reader, headers headers) (*http.Request, error) { - expectedPayload := (method == http.MethodPost || method == http.MethodPut) - if expectedPayload && body == nil { - body = bytes.NewReader([]byte{}) - } - - req, err := http.NewRequest(method, path, body) - if err != nil { - return nil, err - } - req = cli.addHeaders(req, headers) - - if cli.proto == "unix" || cli.proto == "npipe" { - // For local communications, it doesn't matter what the host is. We just - // need a valid and meaningful host name. (See #189) - req.Host = "docker" - } - - req.URL.Host = cli.addr - req.URL.Scheme = cli.scheme - - if expectedPayload && req.Header.Get("Content-Type") == "" { - req.Header.Set("Content-Type", "text/plain") - } - return req, nil -} - -func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers headers) (serverResponse, error) { - req, err := cli.buildRequest(method, cli.getAPIPath(ctx, path, query), body, headers) - if err != nil { - return serverResponse{}, err - } - resp, err := cli.doRequest(ctx, req) - if err != nil { - return resp, errdefs.FromStatusCode(err, resp.statusCode) - } - err = cli.checkResponseErr(resp) - return resp, errdefs.FromStatusCode(err, resp.statusCode) -} - -func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResponse, error) { - serverResp := serverResponse{statusCode: -1, reqURL: req.URL} - - req = req.WithContext(ctx) - resp, err := cli.client.Do(req) - if err != nil { - if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") { - return serverResp, 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, errors.Wrap(err, "The server probably has client authentication (--tlsverify) enabled. Please 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 - } - - if nErr, ok := err.(*url.Error); ok { - if nErr, ok := nErr.Err.(*net.OpError); ok { - if os.IsPermission(nErr.Err) { - return serverResp, errors.Wrapf(err, "Got permission denied while trying to connect to the Docker daemon socket at %v", cli.host) - } - } - } - - if err, ok := err.(net.Error); ok { - if err.Timeout() { - return serverResp, ErrorConnectionFailed(cli.host) - } - if !err.Temporary() { - if strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") { - return serverResp, ErrorConnectionFailed(cli.host) - } - } - } - - // Although there's not a strongly typed error for this in go-winio, - // lots of people are using the default configuration for the docker - // daemon on Windows where the daemon is listening on a named pipe - // `//./pipe/docker_engine, and the client must be running elevated. - // Give users a clue rather than the not-overly useful message - // such as `error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.26/info: - // open //./pipe/docker_engine: The system cannot find the file specified.`. - // Note we can't string compare "The system cannot find the file specified" as - // this is localised - for example in French the error would be - // `open //./pipe/docker_engine: Le fichier spécifié est introuvable.` - if strings.Contains(err.Error(), `open //./pipe/docker_engine`) { - // Checks if client is running with elevated privileges - if f, elevatedErr := os.Open("\\\\.\\PHYSICALDRIVE0"); elevatedErr == nil { - err = errors.Wrap(err, "In the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect.") - } else { - f.Close() - err = errors.Wrap(err, "This error may indicate that the docker daemon is not running.") - } - } - - return serverResp, errors.Wrap(err, "error during connect") - } - - if resp != nil { - serverResp.statusCode = resp.StatusCode - serverResp.body = resp.Body - serverResp.header = resp.Header - } - return serverResp, nil -} - -func (cli *Client) checkResponseErr(serverResp serverResponse) error { - if serverResp.statusCode >= 200 && serverResp.statusCode < 400 { - return nil - } - - var body []byte - var err error - if serverResp.body != nil { - bodyMax := 1 * 1024 * 1024 // 1 MiB - bodyR := &io.LimitedReader{ - R: serverResp.body, - N: int64(bodyMax), - } - body, err = ioutil.ReadAll(bodyR) - if err != nil { - 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 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) - } - - var ct string - if serverResp.header != nil { - ct = serverResp.header.Get("Content-Type") - } - - var errorMessage string - if (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) && ct == "application/json" { - var errorResponse types.ErrorResponse - if err := json.Unmarshal(body, &errorResponse); err != nil { - return errors.Wrap(err, "Error reading JSON") - } - errorMessage = strings.TrimSpace(errorResponse.Message) - } else { - errorMessage = strings.TrimSpace(string(body)) - } - - return errors.Wrap(errors.New(errorMessage), "Error response from daemon") -} - -func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request { - // Add CLI Config's HTTP Headers BEFORE we set the Docker headers - // then the user can't change OUR headers - for k, v := range cli.customHTTPHeaders { - if versions.LessThan(cli.version, "1.25") && k == "User-Agent" { - continue - } - req.Header.Set(k, v) - } - - if headers != nil { - for k, v := range headers { - req.Header[k] = v - } - } - return req -} - -func encodeData(data interface{}) (*bytes.Buffer, error) { - params := bytes.NewBuffer(nil) - if data != nil { - if err := json.NewEncoder(params).Encode(data); err != nil { - return nil, err - } - } - return params, nil -} - -func ensureReaderClosed(response serverResponse) { - if response.body != nil { - // Drain up to 512 bytes and close the body to let the Transport reuse the connection - io.CopyN(ioutil.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 deleted file mode 100644 index fd5b914136c..00000000000 --- a/vendor/github.com/docker/docker/client/secret_create.go +++ /dev/null @@ -1,25 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" -) - -// 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("1.25", "secret create"); err != nil { - return response, err - } - resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil) - defer ensureReaderClosed(resp) - if err != nil { - return response, err - } - - 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 deleted file mode 100644 index d093916c9a4..00000000000 --- a/vendor/github.com/docker/docker/client/secret_inspect.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/swarm" -) - -// 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("1.25", "secret inspect"); err != nil { - return swarm.Secret{}, nil, err - } - if id == "" { - return swarm.Secret{}, nil, objectNotFoundError{object: "secret", id: id} - } - resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) - defer ensureReaderClosed(resp) - if err != nil { - return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id) - } - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return swarm.Secret{}, nil, err - } - - var secret swarm.Secret - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&secret) - - return secret, body, err -} diff --git a/vendor/github.com/docker/docker/client/secret_list.go b/vendor/github.com/docker/docker/client/secret_list.go deleted file mode 100644 index a0289c9f440..00000000000 --- a/vendor/github.com/docker/docker/client/secret_list.go +++ /dev/null @@ -1,38 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" -) - -// SecretList returns the list of secrets. -func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) { - if err := cli.NewVersionError("1.25", "secret list"); err != nil { - return nil, err - } - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/secrets", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return nil, err - } - - var secrets []swarm.Secret - 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 deleted file mode 100644 index c16f5558041..00000000000 --- a/vendor/github.com/docker/docker/client/secret_remove.go +++ /dev/null @@ -1,13 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "context" - -// SecretRemove removes a Secret. -func (cli *Client) SecretRemove(ctx context.Context, id string) error { - if err := cli.NewVersionError("1.25", "secret remove"); err != nil { - return err - } - resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil) - defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "secret", id) -} diff --git a/vendor/github.com/docker/docker/client/secret_update.go b/vendor/github.com/docker/docker/client/secret_update.go deleted file mode 100644 index 164256bbc15..00000000000 --- a/vendor/github.com/docker/docker/client/secret_update.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - "strconv" - - "github.com/docker/docker/api/types/swarm" -) - -// SecretUpdate attempts to update a Secret -func (cli *Client) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error { - if err := cli.NewVersionError("1.25", "secret update"); err != nil { - return err - } - query := url.Values{} - query.Set("version", strconv.FormatUint(version.Index, 10)) - resp, err := cli.post(ctx, "/secrets/"+id+"/update", query, secret, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/service_create.go b/vendor/github.com/docker/docker/client/service_create.go deleted file mode 100644 index e0428bf98b3..00000000000 --- a/vendor/github.com/docker/docker/client/service_create.go +++ /dev/null @@ -1,178 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - "strings" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -// ServiceCreate creates a new Service. -func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) { - var response types.ServiceCreateResponse - headers := map[string][]string{ - "version": {cli.version}, - } - - if options.EncodedRegistryAuth != "" { - headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth} - } - - // Make sure containerSpec is not nil when no runtime is set or the runtime is set to container - if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) { - service.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{} - } - - if err := validateServiceSpec(service); err != nil { - return response, err - } - - // ensure that the image is tagged - var resolveWarning string - switch { - case service.TaskTemplate.ContainerSpec != nil: - if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" { - service.TaskTemplate.ContainerSpec.Image = taggedImg - } - if options.QueryRegistry { - resolveWarning = resolveContainerSpecImage(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) - } - case service.TaskTemplate.PluginSpec != nil: - if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" { - service.TaskTemplate.PluginSpec.Remote = taggedImg - } - if options.QueryRegistry { - resolveWarning = resolvePluginSpecRemote(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) - } - } - - resp, err := cli.post(ctx, "/services/create", nil, service, headers) - defer ensureReaderClosed(resp) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - if resolveWarning != "" { - response.Warnings = append(response.Warnings, resolveWarning) - } - - return response, err -} - -func resolveContainerSpecImage(ctx context.Context, cli DistributionAPIClient, taskSpec *swarm.TaskSpec, encodedAuth string) string { - var warning string - if img, imgPlatforms, err := imageDigestAndPlatforms(ctx, cli, taskSpec.ContainerSpec.Image, encodedAuth); err != nil { - warning = digestWarning(taskSpec.ContainerSpec.Image) - } else { - taskSpec.ContainerSpec.Image = img - if len(imgPlatforms) > 0 { - if taskSpec.Placement == nil { - taskSpec.Placement = &swarm.Placement{} - } - taskSpec.Placement.Platforms = imgPlatforms - } - } - return warning -} - -func resolvePluginSpecRemote(ctx context.Context, cli DistributionAPIClient, taskSpec *swarm.TaskSpec, encodedAuth string) string { - var warning string - if img, imgPlatforms, err := imageDigestAndPlatforms(ctx, cli, taskSpec.PluginSpec.Remote, encodedAuth); err != nil { - warning = digestWarning(taskSpec.PluginSpec.Remote) - } else { - taskSpec.PluginSpec.Remote = img - if len(imgPlatforms) > 0 { - if taskSpec.Placement == nil { - taskSpec.Placement = &swarm.Placement{} - } - taskSpec.Placement.Platforms = imgPlatforms - } - } - return warning -} - -func imageDigestAndPlatforms(ctx context.Context, cli DistributionAPIClient, image, encodedAuth string) (string, []swarm.Platform, error) { - distributionInspect, err := cli.DistributionInspect(ctx, image, encodedAuth) - var platforms []swarm.Platform - if err != nil { - return "", nil, err - } - - imageWithDigest := imageWithDigestString(image, distributionInspect.Descriptor.Digest) - - if len(distributionInspect.Platforms) > 0 { - platforms = make([]swarm.Platform, 0, len(distributionInspect.Platforms)) - for _, p := range distributionInspect.Platforms { - // clear architecture field for arm. This is a temporary patch to address - // https://github.com/docker/swarmkit/issues/2294. The issue is that while - // image manifests report "arm" as the architecture, the node reports - // something like "armv7l" (includes the variant), which causes arm images - // to stop working with swarm mode. This patch removes the architecture - // constraint for arm images to ensure tasks get scheduled. - arch := p.Architecture - if strings.ToLower(arch) == "arm" { - arch = "" - } - platforms = append(platforms, swarm.Platform{ - Architecture: arch, - OS: p.OS, - }) - } - } - return imageWithDigest, platforms, err -} - -// imageWithDigestString takes an image string and a digest, and updates -// the image string if it didn't originally contain a digest. It returns -// image unmodified in other situations. -func imageWithDigestString(image string, dgst digest.Digest) string { - namedRef, err := reference.ParseNormalizedNamed(image) - if err == nil { - if _, isCanonical := namedRef.(reference.Canonical); !isCanonical { - // ensure that image gets a default tag if none is provided - img, err := reference.WithDigest(namedRef, dgst) - if err == nil { - return reference.FamiliarString(img) - } - } - } - return image -} - -// imageWithTagString takes an image string, and returns a tagged image -// string, adding a 'latest' tag if one was not provided. It returns an -// empty string if a canonical reference was provided -func imageWithTagString(image string) string { - namedRef, err := reference.ParseNormalizedNamed(image) - if err == nil { - return reference.FamiliarString(reference.TagNameOnly(namedRef)) - } - return "" -} - -// digestWarning constructs a formatted warning string using the -// image name that could not be pinned by digest. The formatting -// is hardcoded, but could me made smarter in the future -func digestWarning(image string) string { - return fmt.Sprintf("image %s could not be accessed on a registry to record\nits digest. Each node will access %s independently,\npossibly leading to different nodes running different\nversions of the image.\n", image, image) -} - -func validateServiceSpec(s swarm.ServiceSpec) error { - if s.TaskTemplate.ContainerSpec != nil && s.TaskTemplate.PluginSpec != nil { - return errors.New("must not specify both a container spec and a plugin spec in the task template") - } - if s.TaskTemplate.PluginSpec != nil && s.TaskTemplate.Runtime != swarm.RuntimePlugin { - return errors.New("mismatched runtime with plugin spec") - } - if s.TaskTemplate.ContainerSpec != nil && (s.TaskTemplate.Runtime != "" && s.TaskTemplate.Runtime != swarm.RuntimeContainer) { - return errors.New("mismatched runtime with container spec") - } - return nil -} diff --git a/vendor/github.com/docker/docker/client/service_inspect.go b/vendor/github.com/docker/docker/client/service_inspect.go deleted file mode 100644 index 2801483b80f..00000000000 --- a/vendor/github.com/docker/docker/client/service_inspect.go +++ /dev/null @@ -1,37 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" -) - -// 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} - } - query := url.Values{} - query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults)) - serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return swarm.Service{}, nil, wrapResponseError(err, serverResp, "service", serviceID) - } - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return swarm.Service{}, nil, err - } - - var response swarm.Service - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/service_list.go b/vendor/github.com/docker/docker/client/service_list.go deleted file mode 100644 index f97ec75a5cb..00000000000 --- a/vendor/github.com/docker/docker/client/service_list.go +++ /dev/null @@ -1,39 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" -) - -// ServiceList returns the list of services. -func (cli *Client) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - if options.Status { - query.Set("status", "true") - } - - resp, err := cli.get(ctx, "/services", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return nil, err - } - - var services []swarm.Service - 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 deleted file mode 100644 index 906fd4059e6..00000000000 --- a/vendor/github.com/docker/docker/client/service_logs.go +++ /dev/null @@ -1,52 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" - "time" - - "github.com/docker/docker/api/types" - timetypes "github.com/docker/docker/api/types/time" - "github.com/pkg/errors" -) - -// 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 types.ContainerLogsOptions) (io.ReadCloser, error) { - query := url.Values{} - if options.ShowStdout { - query.Set("stdout", "1") - } - - if options.ShowStderr { - query.Set("stderr", "1") - } - - if options.Since != "" { - ts, err := timetypes.GetTimestamp(options.Since, time.Now()) - if err != nil { - return nil, errors.Wrap(err, `invalid value for "since"`) - } - query.Set("since", ts) - } - - if options.Timestamps { - query.Set("timestamps", "1") - } - - if options.Details { - query.Set("details", "1") - } - - if options.Follow { - query.Set("follow", "1") - } - query.Set("tail", options.Tail) - - resp, err := cli.get(ctx, "/services/"+serviceID+"/logs", query, nil) - if err != nil { - return nil, err - } - 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 deleted file mode 100644 index 953a2adf5ae..00000000000 --- a/vendor/github.com/docker/docker/client/service_remove.go +++ /dev/null @@ -1,10 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import "context" - -// ServiceRemove kills and removes a service. -func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error { - resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) - defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "service", serviceID) -} diff --git a/vendor/github.com/docker/docker/client/service_update.go b/vendor/github.com/docker/docker/client/service_update.go deleted file mode 100644 index c63895f74f2..00000000000 --- a/vendor/github.com/docker/docker/client/service_update.go +++ /dev/null @@ -1,75 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - "strconv" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" -) - -// ServiceUpdate updates a Service. The version number is required to avoid conflicting writes. -// 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) (types.ServiceUpdateResponse, error) { - var ( - query = url.Values{} - response = types.ServiceUpdateResponse{} - ) - - headers := map[string][]string{ - "version": {cli.version}, - } - - if options.EncodedRegistryAuth != "" { - headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth} - } - - if options.RegistryAuthFrom != "" { - query.Set("registryAuthFrom", options.RegistryAuthFrom) - } - - if options.Rollback != "" { - query.Set("rollback", options.Rollback) - } - - query.Set("version", strconv.FormatUint(version.Index, 10)) - - if err := validateServiceSpec(service); err != nil { - return response, err - } - - // ensure that the image is tagged - var resolveWarning string - switch { - case service.TaskTemplate.ContainerSpec != nil: - if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" { - service.TaskTemplate.ContainerSpec.Image = taggedImg - } - if options.QueryRegistry { - resolveWarning = resolveContainerSpecImage(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) - } - case service.TaskTemplate.PluginSpec != nil: - if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" { - service.TaskTemplate.PluginSpec.Remote = taggedImg - } - if options.QueryRegistry { - resolveWarning = resolvePluginSpecRemote(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) - } - } - - resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) - defer ensureReaderClosed(resp) - if err != nil { - return response, err - } - - err = json.NewDecoder(resp.body).Decode(&response) - if resolveWarning != "" { - response.Warnings = append(response.Warnings, resolveWarning) - } - - return response, err -} 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 deleted file mode 100644 index 19f59dd582a..00000000000 --- a/vendor/github.com/docker/docker/client/swarm_get_unlock_key.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types" -) - -// 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) - if err != nil { - return types.SwarmUnlockKeyResponse{}, err - } - - var response types.SwarmUnlockKeyResponse - err = json.NewDecoder(serverResp.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 deleted file mode 100644 index da3c1637ef0..00000000000 --- a/vendor/github.com/docker/docker/client/swarm_init.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types/swarm" -) - -// 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) - if err != nil { - return "", err - } - - var response string - err = json.NewDecoder(serverResp.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 deleted file mode 100644 index b52b67a8849..00000000000 --- a/vendor/github.com/docker/docker/client/swarm_inspect.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types/swarm" -) - -// 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) - if err != nil { - return swarm.Swarm{}, err - } - - var response swarm.Swarm - err = json.NewDecoder(serverResp.body).Decode(&response) - return response, err -} diff --git a/vendor/github.com/docker/docker/client/swarm_join.go b/vendor/github.com/docker/docker/client/swarm_join.go deleted file mode 100644 index a1cf0455d2b..00000000000 --- a/vendor/github.com/docker/docker/client/swarm_join.go +++ /dev/null @@ -1,14 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - - "github.com/docker/docker/api/types/swarm" -) - -// SwarmJoin joins the swarm. -func (cli *Client) SwarmJoin(ctx context.Context, req swarm.JoinRequest) error { - resp, err := cli.post(ctx, "/swarm/join", nil, req, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/swarm_leave.go b/vendor/github.com/docker/docker/client/swarm_leave.go deleted file mode 100644 index 90ca84b363b..00000000000 --- a/vendor/github.com/docker/docker/client/swarm_leave.go +++ /dev/null @@ -1,17 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" -) - -// SwarmLeave leaves the swarm. -func (cli *Client) SwarmLeave(ctx context.Context, force bool) error { - query := url.Values{} - if force { - query.Set("force", "1") - } - resp, err := cli.post(ctx, "/swarm/leave", query, nil, nil) - ensureReaderClosed(resp) - return err -} diff --git a/vendor/github.com/docker/docker/client/swarm_unlock.go b/vendor/github.com/docker/docker/client/swarm_unlock.go deleted file mode 100644 index d2412f7d441..00000000000 --- a/vendor/github.com/docker/docker/client/swarm_unlock.go +++ /dev/null @@ -1,14 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - - "github.com/docker/docker/api/types/swarm" -) - -// 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) - return err -} diff --git a/vendor/github.com/docker/docker/client/swarm_update.go b/vendor/github.com/docker/docker/client/swarm_update.go deleted file mode 100644 index 56a5bea761e..00000000000 --- a/vendor/github.com/docker/docker/client/swarm_update.go +++ /dev/null @@ -1,22 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "fmt" - "net/url" - "strconv" - - "github.com/docker/docker/api/types/swarm" -) - -// SwarmUpdate updates the swarm. -func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error { - query := url.Values{} - query.Set("version", strconv.FormatUint(version.Index, 10)) - query.Set("rotateWorkerToken", fmt.Sprintf("%v", flags.RotateWorkerToken)) - query.Set("rotateManagerToken", fmt.Sprintf("%v", flags.RotateManagerToken)) - query.Set("rotateManagerUnlockKey", fmt.Sprintf("%v", flags.RotateManagerUnlockKey)) - resp, err := cli.post(ctx, "/swarm/update", query, swarm, 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 deleted file mode 100644 index 44d40ba5ae8..00000000000 --- a/vendor/github.com/docker/docker/client/task_inspect.go +++ /dev/null @@ -1,32 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types/swarm" -) - -// 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} - } - serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return swarm.Task{}, nil, wrapResponseError(err, serverResp, "task", taskID) - } - - body, err := ioutil.ReadAll(serverResp.body) - if err != nil { - return swarm.Task{}, nil, err - } - - var response swarm.Task - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err -} diff --git a/vendor/github.com/docker/docker/client/task_list.go b/vendor/github.com/docker/docker/client/task_list.go deleted file mode 100644 index 4869b44493b..00000000000 --- a/vendor/github.com/docker/docker/client/task_list.go +++ /dev/null @@ -1,35 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" -) - -// TaskList returns the list of tasks. -func (cli *Client) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { - query := url.Values{} - - if options.Filters.Len() > 0 { - filterJSON, err := filters.ToJSON(options.Filters) - if err != nil { - return nil, err - } - - query.Set("filters", filterJSON) - } - - resp, err := cli.get(ctx, "/tasks", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return nil, err - } - - var tasks []swarm.Task - 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 deleted file mode 100644 index 6222fab577d..00000000000 --- a/vendor/github.com/docker/docker/client/task_logs.go +++ /dev/null @@ -1,51 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "io" - "net/url" - "time" - - "github.com/docker/docker/api/types" - timetypes "github.com/docker/docker/api/types/time" -) - -// TaskLogs returns the logs generated by a task in an io.ReadCloser. -// It's up to the caller to close the stream. -func (cli *Client) TaskLogs(ctx context.Context, taskID string, options types.ContainerLogsOptions) (io.ReadCloser, error) { - query := url.Values{} - if options.ShowStdout { - query.Set("stdout", "1") - } - - if options.ShowStderr { - query.Set("stderr", "1") - } - - if options.Since != "" { - ts, err := timetypes.GetTimestamp(options.Since, time.Now()) - if err != nil { - return nil, err - } - query.Set("since", ts) - } - - if options.Timestamps { - query.Set("timestamps", "1") - } - - if options.Details { - query.Set("details", "1") - } - - if options.Follow { - query.Set("follow", "1") - } - query.Set("tail", options.Tail) - - resp, err := cli.get(ctx, "/tasks/"+taskID+"/logs", query, nil) - if err != nil { - return nil, err - } - return resp.body, nil -} diff --git a/vendor/github.com/docker/docker/client/transport.go b/vendor/github.com/docker/docker/client/transport.go deleted file mode 100644 index 5541344366b..00000000000 --- a/vendor/github.com/docker/docker/client/transport.go +++ /dev/null @@ -1,17 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "crypto/tls" - "net/http" -) - -// resolveTLSConfig attempts to resolve the TLS configuration from the -// RoundTripper. -func resolveTLSConfig(transport http.RoundTripper) *tls.Config { - switch tr := transport.(type) { - case *http.Transport: - return tr.TLSClientConfig - default: - return nil - } -} diff --git a/vendor/github.com/docker/docker/client/utils.go b/vendor/github.com/docker/docker/client/utils.go deleted file mode 100644 index 7f3ff44eb80..00000000000 --- a/vendor/github.com/docker/docker/client/utils.go +++ /dev/null @@ -1,34 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "net/url" - "regexp" - - "github.com/docker/docker/api/types/filters" -) - -var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`) - -// getDockerOS returns the operating system based on the server header from the daemon. -func getDockerOS(serverHeader string) string { - var osType string - matches := headerRegexp.FindStringSubmatch(serverHeader) - if len(matches) > 0 { - osType = matches[1] - } - return osType -} - -// getFiltersQuery returns a url query with "filters" query term, based on the -// filters provided. -func getFiltersQuery(f filters.Args) (url.Values, error) { - query := url.Values{} - if f.Len() > 0 { - filterJSON, err := filters.ToJSON(f) - if err != nil { - return query, err - } - query.Set("filters", filterJSON) - } - return query, nil -} diff --git a/vendor/github.com/docker/docker/client/version.go b/vendor/github.com/docker/docker/client/version.go deleted file mode 100644 index 8f17ff4e87a..00000000000 --- a/vendor/github.com/docker/docker/client/version.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types" -) - -// ServerVersion returns information of the docker client and server host. -func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) { - resp, err := cli.get(ctx, "/version", nil, nil) - defer ensureReaderClosed(resp) - if err != nil { - return types.Version{}, err - } - - var server types.Version - 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 deleted file mode 100644 index 92761b3c639..00000000000 --- a/vendor/github.com/docker/docker/client/volume_create.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - - "github.com/docker/docker/api/types" - volumetypes "github.com/docker/docker/api/types/volume" -) - -// VolumeCreate creates a volume in the docker host. -func (cli *Client) VolumeCreate(ctx context.Context, options volumetypes.VolumeCreateBody) (types.Volume, error) { - var volume types.Volume - resp, err := cli.post(ctx, "/volumes/create", nil, options, nil) - defer ensureReaderClosed(resp) - if err != nil { - return volume, err - } - err = json.NewDecoder(resp.body).Decode(&volume) - return volume, err -} diff --git a/vendor/github.com/docker/docker/client/volume_inspect.go b/vendor/github.com/docker/docker/client/volume_inspect.go deleted file mode 100644 index e20b2c67c7a..00000000000 --- a/vendor/github.com/docker/docker/client/volume_inspect.go +++ /dev/null @@ -1,38 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - - "github.com/docker/docker/api/types" -) - -// VolumeInspect returns the information about a specific volume in the docker host. -func (cli *Client) VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) { - volume, _, err := cli.VolumeInspectWithRaw(ctx, volumeID) - return volume, err -} - -// 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) (types.Volume, []byte, error) { - if volumeID == "" { - return types.Volume{}, nil, objectNotFoundError{object: "volume", id: volumeID} - } - - var volume types.Volume - resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil) - defer ensureReaderClosed(resp) - if err != nil { - return volume, nil, wrapResponseError(err, resp, "volume", volumeID) - } - - body, err := ioutil.ReadAll(resp.body) - if err != nil { - return volume, nil, err - } - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&volume) - return volume, body, err -} diff --git a/vendor/github.com/docker/docker/client/volume_list.go b/vendor/github.com/docker/docker/client/volume_list.go deleted file mode 100644 index 942498dde2c..00000000000 --- a/vendor/github.com/docker/docker/client/volume_list.go +++ /dev/null @@ -1,33 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "net/url" - - "github.com/docker/docker/api/types/filters" - volumetypes "github.com/docker/docker/api/types/volume" -) - -// VolumeList returns the volumes configured in the docker host. -func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumeListOKBody, error) { - var volumes volumetypes.VolumeListOKBody - query := url.Values{} - - if filter.Len() > 0 { - //nolint:staticcheck // ignore SA1019 for old code - filterJSON, err := filters.ToParamWithVersion(cli.version, filter) - if err != nil { - return volumes, err - } - query.Set("filters", filterJSON) - } - resp, err := cli.get(ctx, "/volumes", query, nil) - defer ensureReaderClosed(resp) - if err != nil { - return volumes, err - } - - 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 deleted file mode 100644 index 6e324708f2b..00000000000 --- a/vendor/github.com/docker/docker/client/volume_prune.go +++ /dev/null @@ -1,36 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" -) - -// VolumesPrune requests the daemon to delete unused data -func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (types.VolumesPruneReport, error) { - var report types.VolumesPruneReport - - if err := cli.NewVersionError("1.25", "volume prune"); err != nil { - return report, err - } - - query, err := getFiltersQuery(pruneFilters) - if err != nil { - return report, err - } - - serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil) - defer ensureReaderClosed(serverResp) - if err != nil { - return report, err - } - - if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return report, 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 deleted file mode 100644 index 79decdafab8..00000000000 --- a/vendor/github.com/docker/docker/client/volume_remove.go +++ /dev/null @@ -1,21 +0,0 @@ -package client // import "github.com/docker/docker/client" - -import ( - "context" - "net/url" - - "github.com/docker/docker/api/types/versions" -) - -// VolumeRemove removes a volume from the docker host. -func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error { - query := url.Values{} - if versions.GreaterThanOrEqualTo(cli.version, "1.25") { - if force { - query.Set("force", "1") - } - } - resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil) - defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "volume", volumeID) -} diff --git a/vendor/github.com/docker/docker/errdefs/defs.go b/vendor/github.com/docker/docker/errdefs/defs.go deleted file mode 100644 index 61e7456b4eb..00000000000 --- a/vendor/github.com/docker/docker/errdefs/defs.go +++ /dev/null @@ -1,69 +0,0 @@ -package errdefs // import "github.com/docker/docker/errdefs" - -// ErrNotFound signals that the requested object doesn't exist -type ErrNotFound interface { - NotFound() -} - -// ErrInvalidParameter signals that the user input is invalid -type ErrInvalidParameter interface { - InvalidParameter() -} - -// ErrConflict signals that some internal state conflicts with the requested action and can't be performed. -// A change in state should be able to clear this error. -type ErrConflict interface { - Conflict() -} - -// ErrUnauthorized is used to signify that the user is not authorized to perform a specific action -type ErrUnauthorized interface { - Unauthorized() -} - -// ErrUnavailable signals that the requested action/subsystem is not available. -type ErrUnavailable interface { - Unavailable() -} - -// ErrForbidden signals that the requested action cannot be performed under any circumstances. -// When a ErrForbidden is returned, the caller should never retry the action. -type ErrForbidden interface { - Forbidden() -} - -// ErrSystem signals that some internal error occurred. -// An example of this would be a failed mount request. -type ErrSystem interface { - System() -} - -// ErrNotModified signals that an action can't be performed because it's already in the desired state -type ErrNotModified interface { - NotModified() -} - -// ErrNotImplemented signals that the requested action/feature is not implemented on the system as configured. -type ErrNotImplemented interface { - NotImplemented() -} - -// ErrUnknown signals that the kind of error that occurred is not known. -type ErrUnknown interface { - Unknown() -} - -// ErrCancelled signals that the action was cancelled. -type ErrCancelled interface { - Cancelled() -} - -// ErrDeadline signals that the deadline was reached before the action completed. -type ErrDeadline interface { - DeadlineExceeded() -} - -// ErrDataLoss indicates that data was lost or there is data corruption. -type ErrDataLoss interface { - DataLoss() -} diff --git a/vendor/github.com/docker/docker/errdefs/doc.go b/vendor/github.com/docker/docker/errdefs/doc.go deleted file mode 100644 index c211f174fc1..00000000000 --- a/vendor/github.com/docker/docker/errdefs/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// Package errdefs defines a set of error interfaces that packages should use for communicating classes of errors. -// Errors that cross the package boundary should implement one (and only one) of these interfaces. -// -// Packages should not reference these interfaces directly, only implement them. -// To check if a particular error implements one of these interfaces, there are helper -// functions provided (e.g. `Is`) which can be used rather than asserting the interfaces directly. -// If you must assert on these interfaces, be sure to check the causal chain (`err.Cause()`). -package errdefs // import "github.com/docker/docker/errdefs" diff --git a/vendor/github.com/docker/docker/errdefs/helpers.go b/vendor/github.com/docker/docker/errdefs/helpers.go deleted file mode 100644 index fe06fb6f703..00000000000 --- a/vendor/github.com/docker/docker/errdefs/helpers.go +++ /dev/null @@ -1,279 +0,0 @@ -package errdefs // import "github.com/docker/docker/errdefs" - -import "context" - -type errNotFound struct{ error } - -func (errNotFound) NotFound() {} - -func (e errNotFound) Cause() error { - return e.error -} - -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 -func NotFound(err error) error { - if err == nil || IsNotFound(err) { - return err - } - return errNotFound{err} -} - -type errInvalidParameter struct{ error } - -func (errInvalidParameter) InvalidParameter() {} - -func (e errInvalidParameter) Cause() error { - return e.error -} - -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 -func InvalidParameter(err error) error { - if err == nil || IsInvalidParameter(err) { - return err - } - return errInvalidParameter{err} -} - -type errConflict struct{ error } - -func (errConflict) Conflict() {} - -func (e errConflict) Cause() error { - return e.error -} - -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 -func Conflict(err error) error { - if err == nil || IsConflict(err) { - return err - } - return errConflict{err} -} - -type errUnauthorized struct{ error } - -func (errUnauthorized) Unauthorized() {} - -func (e errUnauthorized) Cause() error { - return e.error -} - -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 -func Unauthorized(err error) error { - if err == nil || IsUnauthorized(err) { - return err - } - return errUnauthorized{err} -} - -type errUnavailable struct{ error } - -func (errUnavailable) Unavailable() {} - -func (e errUnavailable) Cause() error { - return e.error -} - -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 -func Unavailable(err error) error { - if err == nil || IsUnavailable(err) { - return err - } - return errUnavailable{err} -} - -type errForbidden struct{ error } - -func (errForbidden) Forbidden() {} - -func (e errForbidden) Cause() error { - return e.error -} - -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 -func Forbidden(err error) error { - if err == nil || IsForbidden(err) { - return err - } - return errForbidden{err} -} - -type errSystem struct{ error } - -func (errSystem) System() {} - -func (e errSystem) Cause() error { - return e.error -} - -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 -func System(err error) error { - if err == nil || IsSystem(err) { - return err - } - return errSystem{err} -} - -type errNotModified struct{ error } - -func (errNotModified) NotModified() {} - -func (e errNotModified) Cause() error { - return e.error -} - -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 -func NotModified(err error) error { - if err == nil || IsNotModified(err) { - return err - } - return errNotModified{err} -} - -type errNotImplemented struct{ error } - -func (errNotImplemented) NotImplemented() {} - -func (e errNotImplemented) Cause() error { - return e.error -} - -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 -func NotImplemented(err error) error { - if err == nil || IsNotImplemented(err) { - return err - } - return errNotImplemented{err} -} - -type errUnknown struct{ error } - -func (errUnknown) Unknown() {} - -func (e errUnknown) Cause() error { - return e.error -} - -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 -func Unknown(err error) error { - if err == nil || IsUnknown(err) { - return err - } - return errUnknown{err} -} - -type errCancelled struct{ error } - -func (errCancelled) Cancelled() {} - -func (e errCancelled) Cause() error { - return e.error -} - -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 -func Cancelled(err error) error { - if err == nil || IsCancelled(err) { - return err - } - return errCancelled{err} -} - -type errDeadline struct{ error } - -func (errDeadline) DeadlineExceeded() {} - -func (e errDeadline) Cause() error { - return e.error -} - -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 -func Deadline(err error) error { - if err == nil || IsDeadline(err) { - return err - } - return errDeadline{err} -} - -type errDataLoss struct{ error } - -func (errDataLoss) DataLoss() {} - -func (e errDataLoss) Cause() error { - return e.error -} - -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 -func DataLoss(err error) error { - if err == nil || IsDataLoss(err) { - return err - } - return errDataLoss{err} -} - -// FromContext returns the error class from the passed in context -func FromContext(ctx context.Context) error { - e := ctx.Err() - if e == nil { - return nil - } - - if e == context.Canceled { - return Cancelled(e) - } - if e == context.DeadlineExceeded { - return Deadline(e) - } - return Unknown(e) -} diff --git a/vendor/github.com/docker/docker/errdefs/http_helpers.go b/vendor/github.com/docker/docker/errdefs/http_helpers.go deleted file mode 100644 index 07552f1cc1d..00000000000 --- a/vendor/github.com/docker/docker/errdefs/http_helpers.go +++ /dev/null @@ -1,191 +0,0 @@ -package errdefs // import "github.com/docker/docker/errdefs" - -import ( - "fmt" - "net/http" - - containerderrors "github.com/containerd/containerd/errdefs" - "github.com/docker/distribution/registry/api/errcode" - "github.com/sirupsen/logrus" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// GetHTTPErrorStatusCode retrieves status code from error message. -func GetHTTPErrorStatusCode(err error) int { - if err == nil { - logrus.WithFields(logrus.Fields{"error": err}).Error("unexpected HTTP error handling") - return http.StatusInternalServerError - } - - var statusCode int - - // Stop right there - // Are you sure you should be adding a new error class here? Do one of the existing ones work? - - // Note that the below functions are already checking the error causal chain for matches. - switch { - case IsNotFound(err): - statusCode = http.StatusNotFound - case IsInvalidParameter(err): - statusCode = http.StatusBadRequest - case IsConflict(err): - statusCode = http.StatusConflict - case IsUnauthorized(err): - statusCode = http.StatusUnauthorized - case IsUnavailable(err): - statusCode = http.StatusServiceUnavailable - case IsForbidden(err): - statusCode = http.StatusForbidden - case IsNotModified(err): - statusCode = http.StatusNotModified - case IsNotImplemented(err): - statusCode = http.StatusNotImplemented - case IsSystem(err) || IsUnknown(err) || IsDataLoss(err) || IsDeadline(err) || IsCancelled(err): - statusCode = http.StatusInternalServerError - default: - statusCode = statusCodeFromGRPCError(err) - if statusCode != http.StatusInternalServerError { - return statusCode - } - statusCode = statusCodeFromContainerdError(err) - if statusCode != http.StatusInternalServerError { - return statusCode - } - statusCode = statusCodeFromDistributionError(err) - if statusCode != http.StatusInternalServerError { - return statusCode - } - if e, ok := err.(causer); ok { - return GetHTTPErrorStatusCode(e.Cause()) - } - - logrus.WithFields(logrus.Fields{ - "module": "api", - "error_type": fmt.Sprintf("%T", err), - }).Debugf("FIXME: Got an API for which error does not match any expected type!!!: %+v", err) - } - - if statusCode == 0 { - statusCode = http.StatusInternalServerError - } - - return statusCode -} - -// FromStatusCode creates an errdef error, based on the provided HTTP status-code -func FromStatusCode(err error, statusCode int) error { - if err == nil { - return err - } - switch statusCode { - case http.StatusNotFound: - err = NotFound(err) - case http.StatusBadRequest: - err = InvalidParameter(err) - case http.StatusConflict: - err = Conflict(err) - case http.StatusUnauthorized: - err = Unauthorized(err) - case http.StatusServiceUnavailable: - err = Unavailable(err) - case http.StatusForbidden: - err = Forbidden(err) - case http.StatusNotModified: - err = NotModified(err) - case http.StatusNotImplemented: - err = NotImplemented(err) - case http.StatusInternalServerError: - if !IsSystem(err) && !IsUnknown(err) && !IsDataLoss(err) && !IsDeadline(err) && !IsCancelled(err) { - err = System(err) - } - default: - logrus.WithFields(logrus.Fields{ - "module": "api", - "status_code": fmt.Sprintf("%d", statusCode), - }).Debugf("FIXME: Got an status-code for which error does not match any expected type!!!: %d", statusCode) - - switch { - case statusCode >= 200 && statusCode < 400: - // it's a client error - case statusCode >= 400 && statusCode < 500: - err = InvalidParameter(err) - case statusCode >= 500 && statusCode < 600: - err = System(err) - default: - err = Unknown(err) - } - } - return err -} - -// statusCodeFromGRPCError returns status code according to gRPC error -func statusCodeFromGRPCError(err error) int { - switch status.Code(err) { - case codes.InvalidArgument: // code 3 - return http.StatusBadRequest - case codes.NotFound: // code 5 - return http.StatusNotFound - case codes.AlreadyExists: // code 6 - return http.StatusConflict - case codes.PermissionDenied: // code 7 - return http.StatusForbidden - case codes.FailedPrecondition: // code 9 - return http.StatusBadRequest - case codes.Unauthenticated: // code 16 - return http.StatusUnauthorized - case codes.OutOfRange: // code 11 - return http.StatusBadRequest - case codes.Unimplemented: // code 12 - return http.StatusNotImplemented - case codes.Unavailable: // code 14 - return http.StatusServiceUnavailable - default: - // codes.Canceled(1) - // codes.Unknown(2) - // codes.DeadlineExceeded(4) - // codes.ResourceExhausted(8) - // codes.Aborted(10) - // codes.Internal(13) - // codes.DataLoss(15) - return http.StatusInternalServerError - } -} - -// statusCodeFromDistributionError returns status code according to registry errcode -// code is loosely based on errcode.ServeJSON() in docker/distribution -func statusCodeFromDistributionError(err error) int { - switch errs := err.(type) { - case errcode.Errors: - if len(errs) < 1 { - return http.StatusInternalServerError - } - if _, ok := errs[0].(errcode.ErrorCoder); ok { - return statusCodeFromDistributionError(errs[0]) - } - case errcode.ErrorCoder: - return errs.ErrorCode().Descriptor().HTTPStatusCode - } - return http.StatusInternalServerError -} - -// statusCodeFromContainerdError returns status code for containerd errors when -// consumed directly (not through gRPC) -func statusCodeFromContainerdError(err error) int { - switch { - case containerderrors.IsInvalidArgument(err): - return http.StatusBadRequest - case containerderrors.IsNotFound(err): - return http.StatusNotFound - case containerderrors.IsAlreadyExists(err): - return http.StatusConflict - case containerderrors.IsFailedPrecondition(err): - return http.StatusPreconditionFailed - case containerderrors.IsUnavailable(err): - return http.StatusServiceUnavailable - case containerderrors.IsNotImplemented(err): - return http.StatusNotImplemented - default: - return http.StatusInternalServerError - } -} diff --git a/vendor/github.com/docker/docker/errdefs/is.go b/vendor/github.com/docker/docker/errdefs/is.go deleted file mode 100644 index 3abf07d0c35..00000000000 --- a/vendor/github.com/docker/docker/errdefs/is.go +++ /dev/null @@ -1,107 +0,0 @@ -package errdefs // import "github.com/docker/docker/errdefs" - -type causer interface { - Cause() error -} - -func getImplementer(err error) error { - switch e := err.(type) { - case - ErrNotFound, - ErrInvalidParameter, - ErrConflict, - ErrUnauthorized, - ErrUnavailable, - ErrForbidden, - ErrSystem, - ErrNotModified, - ErrNotImplemented, - ErrCancelled, - ErrDeadline, - ErrDataLoss, - ErrUnknown: - return err - case causer: - return getImplementer(e.Cause()) - default: - return err - } -} - -// 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 -func IsInvalidParameter(err error) bool { - _, ok := getImplementer(err).(ErrInvalidParameter) - return ok -} - -// 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 -func IsUnauthorized(err error) bool { - _, ok := getImplementer(err).(ErrUnauthorized) - return ok -} - -// 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 -func IsForbidden(err error) bool { - _, ok := getImplementer(err).(ErrForbidden) - return ok -} - -// 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 -func IsNotModified(err error) bool { - _, ok := getImplementer(err).(ErrNotModified) - return ok -} - -// 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 -func IsUnknown(err error) bool { - _, ok := getImplementer(err).(ErrUnknown) - return ok -} - -// 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 -func IsDeadline(err error) bool { - _, ok := getImplementer(err).(ErrDeadline) - return ok -} - -// 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/pkg/jsonmessage/jsonmessage.go b/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go deleted file mode 100644 index cf8d04b1b20..00000000000 --- a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go +++ /dev/null @@ -1,283 +0,0 @@ -package jsonmessage // import "github.com/docker/docker/pkg/jsonmessage" - -import ( - "encoding/json" - "fmt" - "io" - "strings" - "time" - - units "github.com/docker/go-units" - "github.com/moby/term" - "github.com/morikuni/aec" -) - -// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to -// ensure the formatted time isalways the same number of characters. -const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00" - -// JSONError wraps a concrete Code and Message, `Code` is -// is an integer error code, `Message` is the error message. -type JSONError struct { - Code int `json:"code,omitempty"` - Message string `json:"message,omitempty"` -} - -func (e *JSONError) Error() string { - return e.Message -} - -// JSONProgress describes a Progress. terminalFd is the fd of the current terminal, -// Start is the initial value for the operation. Current is the current status and -// value of the progress made towards Total. Total is the end value describing when -// we made 100% progress for an operation. -type JSONProgress struct { - terminalFd uintptr - Current int64 `json:"current,omitempty"` - Total int64 `json:"total,omitempty"` - Start int64 `json:"start,omitempty"` - // If true, don't show xB/yB - HideCounts bool `json:"hidecounts,omitempty"` - Units string `json:"units,omitempty"` - nowFunc func() time.Time - winSize int -} - -func (p *JSONProgress) String() string { - var ( - width = p.width() - pbBox string - numbersBox string - timeLeftBox string - ) - if p.Current <= 0 && p.Total <= 0 { - return "" - } - if p.Total <= 0 { - switch p.Units { - case "": - current := units.HumanSize(float64(p.Current)) - return fmt.Sprintf("%8v", current) - default: - return fmt.Sprintf("%d %s", p.Current, p.Units) - } - } - - percentage := int(float64(p.Current)/float64(p.Total)*100) / 2 - if percentage > 50 { - percentage = 50 - } - if width > 110 { - // this number can't be negative gh#7136 - numSpaces := 0 - if 50-percentage > 0 { - numSpaces = 50 - percentage - } - pbBox = fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", numSpaces)) - } - - switch { - case p.HideCounts: - case p.Units == "": // no units, use bytes - current := units.HumanSize(float64(p.Current)) - total := units.HumanSize(float64(p.Total)) - - numbersBox = fmt.Sprintf("%8v/%v", current, total) - - if p.Current > p.Total { - // remove total display if the reported current is wonky. - numbersBox = fmt.Sprintf("%8v", current) - } - default: - numbersBox = fmt.Sprintf("%d/%d %s", p.Current, p.Total, p.Units) - - if p.Current > p.Total { - // remove total display if the reported current is wonky. - numbersBox = fmt.Sprintf("%d %s", p.Current, p.Units) - } - } - - if p.Current > 0 && p.Start > 0 && percentage < 50 { - fromStart := p.now().Sub(time.Unix(p.Start, 0)) - perEntry := fromStart / time.Duration(p.Current) - left := time.Duration(p.Total-p.Current) * perEntry - left = (left / time.Second) * time.Second - - if width > 50 { - timeLeftBox = " " + left.String() - } - } - return pbBox + numbersBox + timeLeftBox -} - -// shim for testing -func (p *JSONProgress) now() time.Time { - if p.nowFunc == nil { - p.nowFunc = func() time.Time { - return time.Now().UTC() - } - } - return p.nowFunc() -} - -// shim for testing -func (p *JSONProgress) width() int { - if p.winSize != 0 { - return p.winSize - } - ws, err := term.GetWinsize(p.terminalFd) - if err == nil { - return int(ws.Width) - } - return 200 -} - -// JSONMessage defines a message struct. It describes -// the created time, where it from, status, ID of the -// message. It's used for docker events. -type JSONMessage struct { - Stream string `json:"stream,omitempty"` - Status string `json:"status,omitempty"` - Progress *JSONProgress `json:"progressDetail,omitempty"` - ProgressMessage string `json:"progress,omitempty"` // deprecated - ID string `json:"id,omitempty"` - From string `json:"from,omitempty"` - Time int64 `json:"time,omitempty"` - TimeNano int64 `json:"timeNano,omitempty"` - Error *JSONError `json:"errorDetail,omitempty"` - ErrorMessage string `json:"error,omitempty"` // deprecated - // Aux contains out-of-band data, such as digests for push signing and image id after building. - Aux *json.RawMessage `json:"aux,omitempty"` -} - -func clearLine(out io.Writer) { - eraseMode := aec.EraseModes.All - cl := aec.EraseLine(eraseMode) - fmt.Fprint(out, cl) -} - -func cursorUp(out io.Writer, l uint) { - fmt.Fprint(out, aec.Up(l)) -} - -func cursorDown(out io.Writer, l uint) { - fmt.Fprint(out, aec.Down(l)) -} - -// Display displays the JSONMessage to `out`. If `isTerminal` is true, it will erase the -// entire current line when displaying the progressbar. -func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error { - if jm.Error != nil { - if jm.Error.Code == 401 { - return fmt.Errorf("authentication is required") - } - return jm.Error - } - var endl string - if isTerminal && jm.Stream == "" && jm.Progress != nil { - clearLine(out) - endl = "\r" - fmt.Fprint(out, endl) - } else if jm.Progress != nil && jm.Progress.String() != "" { // disable progressbar in non-terminal - return nil - } - if jm.TimeNano != 0 { - fmt.Fprintf(out, "%s ", time.Unix(0, jm.TimeNano).Format(RFC3339NanoFixed)) - } else if jm.Time != 0 { - fmt.Fprintf(out, "%s ", time.Unix(jm.Time, 0).Format(RFC3339NanoFixed)) - } - if jm.ID != "" { - fmt.Fprintf(out, "%s: ", jm.ID) - } - if jm.From != "" { - fmt.Fprintf(out, "(from %s) ", jm.From) - } - if jm.Progress != nil && isTerminal { - fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl) - } else if jm.ProgressMessage != "" { // deprecated - fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl) - } else if jm.Stream != "" { - fmt.Fprintf(out, "%s%s", jm.Stream, endl) - } else { - fmt.Fprintf(out, "%s%s\n", jm.Status, endl) - } - return nil -} - -// DisplayJSONMessagesStream displays a json message stream from `in` to `out`, `isTerminal` -// describes if `out` is a terminal. If this is the case, it will print `\n` at the end of -// each line and move the cursor while displaying. -func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error { - var ( - dec = json.NewDecoder(in) - ids = make(map[string]uint) - ) - - for { - var diff uint - var jm JSONMessage - if err := dec.Decode(&jm); err != nil { - if err == io.EOF { - break - } - return err - } - - if jm.Aux != nil { - if auxCallback != nil { - auxCallback(jm) - } - continue - } - - if jm.Progress != nil { - jm.Progress.terminalFd = terminalFd - } - if jm.ID != "" && (jm.Progress != nil || jm.ProgressMessage != "") { - line, ok := ids[jm.ID] - if !ok { - // NOTE: This approach of using len(id) to - // figure out the number of lines of history - // only works as long as we clear the history - // when we output something that's not - // accounted for in the map, such as a line - // with no ID. - line = uint(len(ids)) - ids[jm.ID] = line - if isTerminal { - fmt.Fprintf(out, "\n") - } - } - diff = uint(len(ids)) - line - if isTerminal { - cursorUp(out, diff) - } - } else { - // When outputting something that isn't progress - // output, clear the history of previous lines. We - // don't want progress entries from some previous - // operation to be updated (for example, pull -a - // with multiple tags). - ids = make(map[string]uint) - } - err := jm.Display(out, isTerminal) - if jm.ID != "" && isTerminal { - cursorDown(out, diff) - } - if err != nil { - return err - } - } - return nil -} - -type stream interface { - io.Writer - FD() uintptr - IsTerminal() bool -} - -// DisplayJSONMessagesToStream prints json messages to the output stream -func DisplayJSONMessagesToStream(in io.Reader, stream stream, auxCallback func(JSONMessage)) error { - return DisplayJSONMessagesStream(in, stream, stream.FD(), stream.IsTerminal(), auxCallback) -} diff --git a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go b/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go deleted file mode 100644 index 8f6e0a737aa..00000000000 --- a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go +++ /dev/null @@ -1,190 +0,0 @@ -package stdcopy // import "github.com/docker/docker/pkg/stdcopy" - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "sync" -) - -// StdType is the type of standard stream -// a writer can multiplex to. -type StdType byte - -const ( - // Stdin represents standard input stream type. - Stdin StdType = iota - // Stdout represents standard output stream type. - Stdout - // Stderr represents standard error steam type. - Stderr - // Systemerr represents errors originating from the system that make it - // into the multiplexed stream. - Systemerr - - stdWriterPrefixLen = 8 - stdWriterFdIndex = 0 - stdWriterSizeIndex = 4 - - startingBufLen = 32*1024 + stdWriterPrefixLen + 1 -) - -var bufPool = &sync.Pool{New: func() interface{} { return bytes.NewBuffer(nil) }} - -// stdWriter is wrapper of io.Writer with extra customized info. -type stdWriter struct { - io.Writer - prefix byte -} - -// Write sends the buffer to the underneath writer. -// It inserts the prefix header before the buffer, -// so stdcopy.StdCopy knows where to multiplex the output. -// It makes stdWriter to implement io.Writer. -func (w *stdWriter) Write(p []byte) (n int, err error) { - if w == nil || w.Writer == nil { - return 0, errors.New("Writer not instantiated") - } - if p == nil { - return 0, nil - } - - header := [stdWriterPrefixLen]byte{stdWriterFdIndex: w.prefix} - binary.BigEndian.PutUint32(header[stdWriterSizeIndex:], uint32(len(p))) - buf := bufPool.Get().(*bytes.Buffer) - buf.Write(header[:]) - buf.Write(p) - - n, err = w.Writer.Write(buf.Bytes()) - n -= stdWriterPrefixLen - if n < 0 { - n = 0 - } - - buf.Reset() - bufPool.Put(buf) - return -} - -// NewStdWriter instantiates a new Writer. -// Everything written to it will be encapsulated using a custom format, -// and written to the underlying `w` stream. -// This allows multiple write streams (e.g. stdout and stderr) to be muxed into a single connection. -// `t` indicates the id of the stream to encapsulate. -// It can be stdcopy.Stdin, stdcopy.Stdout, stdcopy.Stderr. -func NewStdWriter(w io.Writer, t StdType) io.Writer { - return &stdWriter{ - Writer: w, - prefix: byte(t), - } -} - -// StdCopy is a modified version of io.Copy. -// -// StdCopy will demultiplex `src`, assuming that it contains two streams, -// previously multiplexed together using a StdWriter instance. -// As it reads from `src`, StdCopy will write to `dstout` and `dsterr`. -// -// StdCopy will read until it hits EOF on `src`. It will then return a nil error. -// In other words: if `err` is non nil, it indicates a real underlying error. -// -// `written` will hold the total number of bytes written to `dstout` and `dsterr`. -func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) { - var ( - buf = make([]byte, startingBufLen) - bufLen = len(buf) - nr, nw int - er, ew error - out io.Writer - frameSize int - ) - - for { - // Make sure we have at least a full header - for nr < stdWriterPrefixLen { - var nr2 int - nr2, er = src.Read(buf[nr:]) - nr += nr2 - if er == io.EOF { - if nr < stdWriterPrefixLen { - return written, nil - } - break - } - if er != nil { - return 0, er - } - } - - stream := StdType(buf[stdWriterFdIndex]) - // Check the first byte to know where to write - switch stream { - case Stdin: - fallthrough - case Stdout: - // Write on stdout - out = dstout - case Stderr: - // Write on stderr - out = dsterr - case Systemerr: - // If we're on Systemerr, we won't write anywhere. - // NB: if this code changes later, make sure you don't try to write - // to outstream if Systemerr is the stream - out = nil - default: - return 0, fmt.Errorf("Unrecognized input header: %d", buf[stdWriterFdIndex]) - } - - // Retrieve the size of the frame - frameSize = int(binary.BigEndian.Uint32(buf[stdWriterSizeIndex : stdWriterSizeIndex+4])) - - // Check if the buffer is big enough to read the frame. - // Extend it if necessary. - if frameSize+stdWriterPrefixLen > bufLen { - buf = append(buf, make([]byte, frameSize+stdWriterPrefixLen-bufLen+1)...) - bufLen = len(buf) - } - - // While the amount of bytes read is less than the size of the frame + header, we keep reading - for nr < frameSize+stdWriterPrefixLen { - var nr2 int - nr2, er = src.Read(buf[nr:]) - nr += nr2 - if er == io.EOF { - if nr < frameSize+stdWriterPrefixLen { - return written, nil - } - break - } - if er != nil { - return 0, er - } - } - - // we might have an error from the source mixed up in our multiplexed - // stream. if we do, return it. - if stream == Systemerr { - return written, fmt.Errorf("error from daemon in stream: %s", string(buf[stdWriterPrefixLen:frameSize+stdWriterPrefixLen])) - } - - // Write the retrieved frame (without header) - nw, ew = out.Write(buf[stdWriterPrefixLen : frameSize+stdWriterPrefixLen]) - if ew != nil { - return 0, ew - } - - // If the frame has not been fully written: error - if nw != frameSize { - return 0, io.ErrShortWrite - } - written += int64(nw) - - // Move the rest of the buffer to the beginning - copy(buf, buf[frameSize+stdWriterPrefixLen:]) - // Move the index - nr -= frameSize + stdWriterPrefixLen - } -} diff --git a/vendor/github.com/docker/go-connections/LICENSE b/vendor/github.com/docker/go-connections/LICENSE deleted file mode 100644 index b55b37bc316..00000000000 --- a/vendor/github.com/docker/go-connections/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 2015 Docker, Inc. - - 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/docker/go-connections/nat/nat.go b/vendor/github.com/docker/go-connections/nat/nat.go deleted file mode 100644 index bb7e4e33695..00000000000 --- a/vendor/github.com/docker/go-connections/nat/nat.go +++ /dev/null @@ -1,242 +0,0 @@ -// Package nat is a convenience package for manipulation of strings describing network ports. -package nat - -import ( - "fmt" - "net" - "strconv" - "strings" -) - -const ( - // portSpecTemplate is the expected format for port specifications - portSpecTemplate = "ip:hostPort:containerPort" -) - -// PortBinding represents a binding between a Host IP address and a Host Port -type PortBinding struct { - // HostIP is the host IP Address - HostIP string `json:"HostIp"` - // HostPort is the host port number - HostPort string -} - -// PortMap is a collection of PortBinding indexed by Port -type PortMap map[Port][]PortBinding - -// PortSet is a collection of structs indexed by Port -type PortSet map[Port]struct{} - -// Port is a string containing port number and protocol in the format "80/tcp" -type Port string - -// NewPort creates a new instance of a Port given a protocol and port number or port range -func NewPort(proto, port string) (Port, error) { - // Check for parsing issues on "port" now so we can avoid having - // to check it later on. - - portStartInt, portEndInt, err := ParsePortRangeToInt(port) - if err != nil { - return "", err - } - - if portStartInt == portEndInt { - return Port(fmt.Sprintf("%d/%s", portStartInt, proto)), nil - } - return Port(fmt.Sprintf("%d-%d/%s", portStartInt, portEndInt, proto)), nil -} - -// ParsePort parses the port number string and returns an int -func ParsePort(rawPort string) (int, error) { - if len(rawPort) == 0 { - return 0, nil - } - port, err := strconv.ParseUint(rawPort, 10, 16) - if err != nil { - return 0, err - } - return int(port), nil -} - -// ParsePortRangeToInt parses the port range string and returns start/end ints -func ParsePortRangeToInt(rawPort string) (int, int, error) { - if len(rawPort) == 0 { - return 0, 0, nil - } - start, end, err := ParsePortRange(rawPort) - if err != nil { - return 0, 0, err - } - return int(start), int(end), nil -} - -// Proto returns the protocol of a Port -func (p Port) Proto() string { - proto, _ := SplitProtoPort(string(p)) - return proto -} - -// Port returns the port number of a Port -func (p Port) Port() string { - _, port := SplitProtoPort(string(p)) - return port -} - -// Int returns the port number of a Port as an int -func (p Port) Int() int { - portStr := p.Port() - // We don't need to check for an error because we're going to - // assume that any error would have been found, and reported, in NewPort() - port, _ := ParsePort(portStr) - return port -} - -// Range returns the start/end port numbers of a Port range as ints -func (p Port) Range() (int, int, error) { - return ParsePortRangeToInt(p.Port()) -} - -// SplitProtoPort splits a port in the format of proto/port -func SplitProtoPort(rawPort string) (string, string) { - parts := strings.Split(rawPort, "/") - l := len(parts) - if len(rawPort) == 0 || l == 0 || len(parts[0]) == 0 { - return "", "" - } - if l == 1 { - return "tcp", rawPort - } - if len(parts[1]) == 0 { - return "tcp", parts[0] - } - return parts[1], parts[0] -} - -func validateProto(proto string) bool { - for _, availableProto := range []string{"tcp", "udp", "sctp"} { - if availableProto == proto { - return true - } - } - return false -} - -// ParsePortSpecs receives port specs in the format of ip:public:private/proto and parses -// these in to the internal types -func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding, error) { - var ( - exposedPorts = make(map[Port]struct{}, len(ports)) - bindings = make(map[Port][]PortBinding) - ) - for _, rawPort := range ports { - portMappings, err := ParsePortSpec(rawPort) - if err != nil { - return nil, nil, err - } - - for _, portMapping := range portMappings { - port := portMapping.Port - if _, exists := exposedPorts[port]; !exists { - exposedPorts[port] = struct{}{} - } - bslice, exists := bindings[port] - if !exists { - bslice = []PortBinding{} - } - bindings[port] = append(bslice, portMapping.Binding) - } - } - return exposedPorts, bindings, nil -} - -// PortMapping is a data object mapping a Port to a PortBinding -type PortMapping struct { - Port Port - Binding PortBinding -} - -func splitParts(rawport string) (string, string, string) { - parts := strings.Split(rawport, ":") - n := len(parts) - containerport := parts[n-1] - - switch n { - case 1: - return "", "", containerport - case 2: - return "", parts[0], containerport - case 3: - return parts[0], parts[1], containerport - default: - return strings.Join(parts[:n-2], ":"), parts[n-2], containerport - } -} - -// ParsePortSpec parses a port specification string into a slice of PortMappings -func ParsePortSpec(rawPort string) ([]PortMapping, error) { - var proto string - rawIP, hostPort, containerPort := splitParts(rawPort) - proto, containerPort = SplitProtoPort(containerPort) - - // Strip [] from IPV6 addresses - ip, _, err := net.SplitHostPort(rawIP + ":") - if err != nil { - return nil, fmt.Errorf("Invalid ip address %v: %s", rawIP, err) - } - if ip != "" && net.ParseIP(ip) == nil { - return nil, fmt.Errorf("Invalid ip address: %s", ip) - } - if containerPort == "" { - return nil, fmt.Errorf("No port specified: %s", rawPort) - } - - startPort, endPort, err := ParsePortRange(containerPort) - if err != nil { - return nil, fmt.Errorf("Invalid containerPort: %s", containerPort) - } - - var startHostPort, endHostPort uint64 = 0, 0 - if len(hostPort) > 0 { - startHostPort, endHostPort, err = ParsePortRange(hostPort) - if err != nil { - return nil, fmt.Errorf("Invalid hostPort: %s", hostPort) - } - } - - if hostPort != "" && (endPort-startPort) != (endHostPort-startHostPort) { - // Allow host port range iff containerPort is not a range. - // In this case, use the host port range as the dynamic - // host port range to allocate into. - if endPort != startPort { - return nil, fmt.Errorf("Invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort) - } - } - - if !validateProto(strings.ToLower(proto)) { - return nil, fmt.Errorf("Invalid proto: %s", proto) - } - - ports := []PortMapping{} - for i := uint64(0); i <= (endPort - startPort); i++ { - containerPort = strconv.FormatUint(startPort+i, 10) - if len(hostPort) > 0 { - hostPort = strconv.FormatUint(startHostPort+i, 10) - } - // Set hostPort to a range only if there is a single container port - // and a dynamic host port. - if startPort == endPort && startHostPort != endHostPort { - hostPort = fmt.Sprintf("%s-%s", hostPort, strconv.FormatUint(endHostPort, 10)) - } - port, err := NewPort(strings.ToLower(proto), containerPort) - if err != nil { - return nil, err - } - - binding := PortBinding{ - HostIP: ip, - HostPort: hostPort, - } - ports = append(ports, PortMapping{Port: port, Binding: binding}) - } - return ports, nil -} diff --git a/vendor/github.com/docker/go-connections/nat/parse.go b/vendor/github.com/docker/go-connections/nat/parse.go deleted file mode 100644 index 892adf8c667..00000000000 --- a/vendor/github.com/docker/go-connections/nat/parse.go +++ /dev/null @@ -1,57 +0,0 @@ -package nat - -import ( - "fmt" - "strconv" - "strings" -) - -// PartParser parses and validates the specified string (data) using the specified template -// e.g. ip:public:private -> 192.168.0.1:80:8000 -// DEPRECATED: do not use, this function may be removed in a future version -func PartParser(template, data string) (map[string]string, error) { - // ip:public:private - var ( - templateParts = strings.Split(template, ":") - parts = strings.Split(data, ":") - out = make(map[string]string, len(templateParts)) - ) - if len(parts) != len(templateParts) { - return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template) - } - - for i, t := range templateParts { - value := "" - if len(parts) > i { - value = parts[i] - } - out[t] = value - } - return out, nil -} - -// ParsePortRange parses and validates the specified string as a port-range (8000-9000) -func ParsePortRange(ports string) (uint64, uint64, error) { - if ports == "" { - return 0, 0, fmt.Errorf("Empty string specified for ports.") - } - if !strings.Contains(ports, "-") { - start, err := strconv.ParseUint(ports, 10, 16) - end := start - return start, end, err - } - - parts := strings.Split(ports, "-") - start, err := strconv.ParseUint(parts[0], 10, 16) - if err != nil { - return 0, 0, err - } - end, err := strconv.ParseUint(parts[1], 10, 16) - if err != nil { - return 0, 0, err - } - if end < start { - return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports) - } - return start, end, nil -} diff --git a/vendor/github.com/docker/go-connections/nat/sort.go b/vendor/github.com/docker/go-connections/nat/sort.go deleted file mode 100644 index ce950171e31..00000000000 --- a/vendor/github.com/docker/go-connections/nat/sort.go +++ /dev/null @@ -1,96 +0,0 @@ -package nat - -import ( - "sort" - "strings" -) - -type portSorter struct { - ports []Port - by func(i, j Port) bool -} - -func (s *portSorter) Len() int { - return len(s.ports) -} - -func (s *portSorter) Swap(i, j int) { - s.ports[i], s.ports[j] = s.ports[j], s.ports[i] -} - -func (s *portSorter) Less(i, j int) bool { - ip := s.ports[i] - jp := s.ports[j] - - return s.by(ip, jp) -} - -// Sort sorts a list of ports using the provided predicate -// This function should compare `i` and `j`, returning true if `i` is -// considered to be less than `j` -func Sort(ports []Port, predicate func(i, j Port) bool) { - s := &portSorter{ports, predicate} - sort.Sort(s) -} - -type portMapEntry struct { - port Port - binding PortBinding -} - -type portMapSorter []portMapEntry - -func (s portMapSorter) Len() int { return len(s) } -func (s portMapSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// sort the port so that the order is: -// 1. port with larger specified bindings -// 2. larger port -// 3. port with tcp protocol -func (s portMapSorter) Less(i, j int) bool { - pi, pj := s[i].port, s[j].port - hpi, hpj := toInt(s[i].binding.HostPort), toInt(s[j].binding.HostPort) - return hpi > hpj || pi.Int() > pj.Int() || (pi.Int() == pj.Int() && strings.ToLower(pi.Proto()) == "tcp") -} - -// SortPortMap sorts the list of ports and their respected mapping. The ports -// will explicit HostPort will be placed first. -func SortPortMap(ports []Port, bindings PortMap) { - s := portMapSorter{} - for _, p := range ports { - if binding, ok := bindings[p]; ok { - for _, b := range binding { - s = append(s, portMapEntry{port: p, binding: b}) - } - bindings[p] = []PortBinding{} - } else { - s = append(s, portMapEntry{port: p}) - } - } - - sort.Sort(s) - var ( - i int - pm = make(map[Port]struct{}) - ) - // reorder ports - for _, entry := range s { - if _, ok := pm[entry.port]; !ok { - ports[i] = entry.port - pm[entry.port] = struct{}{} - i++ - } - // reorder bindings for this port - if _, ok := bindings[entry.port]; ok { - bindings[entry.port] = append(bindings[entry.port], entry.binding) - } - } -} - -func toInt(s string) uint64 { - i, _, err := ParsePortRange(s) - if err != nil { - i = 0 - } - return i -} diff --git a/vendor/github.com/docker/go-connections/sockets/README.md b/vendor/github.com/docker/go-connections/sockets/README.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/vendor/github.com/docker/go-connections/sockets/inmem_socket.go b/vendor/github.com/docker/go-connections/sockets/inmem_socket.go deleted file mode 100644 index 99846ffddb1..00000000000 --- a/vendor/github.com/docker/go-connections/sockets/inmem_socket.go +++ /dev/null @@ -1,81 +0,0 @@ -package sockets - -import ( - "errors" - "net" - "sync" -) - -var errClosed = errors.New("use of closed network connection") - -// InmemSocket implements net.Listener using in-memory only connections. -type InmemSocket struct { - chConn chan net.Conn - chClose chan struct{} - addr string - mu sync.Mutex -} - -// dummyAddr is used to satisfy net.Addr for the in-mem socket -// it is just stored as a string and returns the string for all calls -type dummyAddr string - -// NewInmemSocket creates an in-memory only net.Listener -// The addr argument can be any string, but is used to satisfy the `Addr()` part -// of the net.Listener interface -func NewInmemSocket(addr string, bufSize int) *InmemSocket { - return &InmemSocket{ - chConn: make(chan net.Conn, bufSize), - chClose: make(chan struct{}), - addr: addr, - } -} - -// Addr returns the socket's addr string to satisfy net.Listener -func (s *InmemSocket) Addr() net.Addr { - return dummyAddr(s.addr) -} - -// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn. -func (s *InmemSocket) Accept() (net.Conn, error) { - select { - case conn := <-s.chConn: - return conn, nil - case <-s.chClose: - return nil, errClosed - } -} - -// Close closes the listener. It will be unavailable for use once closed. -func (s *InmemSocket) Close() error { - s.mu.Lock() - defer s.mu.Unlock() - select { - case <-s.chClose: - default: - close(s.chClose) - } - return nil -} - -// Dial is used to establish a connection with the in-mem server -func (s *InmemSocket) Dial(network, addr string) (net.Conn, error) { - srvConn, clientConn := net.Pipe() - select { - case s.chConn <- srvConn: - case <-s.chClose: - return nil, errClosed - } - - return clientConn, nil -} - -// Network returns the addr string, satisfies net.Addr -func (a dummyAddr) Network() string { - return string(a) -} - -// String returns the string form -func (a dummyAddr) String() string { - return string(a) -} diff --git a/vendor/github.com/docker/go-connections/sockets/proxy.go b/vendor/github.com/docker/go-connections/sockets/proxy.go deleted file mode 100644 index 98e9a1dc61b..00000000000 --- a/vendor/github.com/docker/go-connections/sockets/proxy.go +++ /dev/null @@ -1,51 +0,0 @@ -package sockets - -import ( - "net" - "net/url" - "os" - "strings" - - "golang.org/x/net/proxy" -) - -// GetProxyEnv allows access to the uppercase and the lowercase forms of -// proxy-related variables. See the Go specification for details on these -// variables. https://golang.org/pkg/net/http/ -func GetProxyEnv(key string) string { - proxyValue := os.Getenv(strings.ToUpper(key)) - if proxyValue == "" { - return os.Getenv(strings.ToLower(key)) - } - return proxyValue -} - -// DialerFromEnvironment takes in a "direct" *net.Dialer and returns a -// proxy.Dialer which will route the connections through the proxy using the -// given dialer. -func DialerFromEnvironment(direct *net.Dialer) (proxy.Dialer, error) { - allProxy := GetProxyEnv("all_proxy") - if len(allProxy) == 0 { - return direct, nil - } - - proxyURL, err := url.Parse(allProxy) - if err != nil { - return direct, err - } - - proxyFromURL, err := proxy.FromURL(proxyURL, direct) - if err != nil { - return direct, err - } - - noProxy := GetProxyEnv("no_proxy") - if len(noProxy) == 0 { - return proxyFromURL, nil - } - - perHost := proxy.NewPerHost(proxyFromURL, direct) - perHost.AddFromString(noProxy) - - return perHost, nil -} diff --git a/vendor/github.com/docker/go-connections/sockets/sockets.go b/vendor/github.com/docker/go-connections/sockets/sockets.go deleted file mode 100644 index a1d7beb4d80..00000000000 --- a/vendor/github.com/docker/go-connections/sockets/sockets.go +++ /dev/null @@ -1,38 +0,0 @@ -// Package sockets provides helper functions to create and configure Unix or TCP sockets. -package sockets - -import ( - "errors" - "net" - "net/http" - "time" -) - -// Why 32? See https://github.com/docker/docker/pull/8035. -const defaultTimeout = 32 * time.Second - -// ErrProtocolNotAvailable is returned when a given transport protocol is not provided by the operating system. -var ErrProtocolNotAvailable = errors.New("protocol not available") - -// ConfigureTransport configures the specified Transport according to the -// specified proto and addr. -// If the proto is unix (using a unix socket to communicate) or npipe the -// compression is disabled. -func ConfigureTransport(tr *http.Transport, proto, addr string) error { - switch proto { - case "unix": - return configureUnixTransport(tr, proto, addr) - case "npipe": - return configureNpipeTransport(tr, proto, addr) - default: - tr.Proxy = http.ProxyFromEnvironment - dialer, err := DialerFromEnvironment(&net.Dialer{ - Timeout: defaultTimeout, - }) - if err != nil { - return err - } - tr.Dial = dialer.Dial - } - return nil -} diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go b/vendor/github.com/docker/go-connections/sockets/sockets_unix.go deleted file mode 100644 index 386cf0dbbde..00000000000 --- a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go +++ /dev/null @@ -1,35 +0,0 @@ -// +build !windows - -package sockets - -import ( - "fmt" - "net" - "net/http" - "syscall" - "time" -) - -const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path) - -func configureUnixTransport(tr *http.Transport, proto, addr string) error { - if len(addr) > maxUnixSocketPathSize { - return fmt.Errorf("Unix socket path %q is too long", addr) - } - // No need for compression in local communications. - tr.DisableCompression = true - tr.Dial = func(_, _ string) (net.Conn, error) { - return net.DialTimeout(proto, addr, defaultTimeout) - } - return nil -} - -func configureNpipeTransport(tr *http.Transport, proto, addr string) error { - return ErrProtocolNotAvailable -} - -// DialPipe connects to a Windows named pipe. -// This is not supported on other OSes. -func DialPipe(_ string, _ time.Duration) (net.Conn, error) { - return nil, syscall.EAFNOSUPPORT -} diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go b/vendor/github.com/docker/go-connections/sockets/sockets_windows.go deleted file mode 100644 index 5c21644e1fe..00000000000 --- a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go +++ /dev/null @@ -1,27 +0,0 @@ -package sockets - -import ( - "net" - "net/http" - "time" - - "github.com/Microsoft/go-winio" -) - -func configureUnixTransport(tr *http.Transport, proto, addr string) error { - return ErrProtocolNotAvailable -} - -func configureNpipeTransport(tr *http.Transport, proto, addr string) error { - // No need for compression in local communications. - tr.DisableCompression = true - tr.Dial = func(_, _ string) (net.Conn, error) { - return DialPipe(addr, defaultTimeout) - } - return nil -} - -// DialPipe connects to a Windows named pipe. -func DialPipe(addr string, timeout time.Duration) (net.Conn, error) { - return winio.DialPipe(addr, &timeout) -} diff --git a/vendor/github.com/docker/go-connections/sockets/tcp_socket.go b/vendor/github.com/docker/go-connections/sockets/tcp_socket.go deleted file mode 100644 index 53cbb6c79e4..00000000000 --- a/vendor/github.com/docker/go-connections/sockets/tcp_socket.go +++ /dev/null @@ -1,22 +0,0 @@ -// Package sockets provides helper functions to create and configure Unix or TCP sockets. -package sockets - -import ( - "crypto/tls" - "net" -) - -// NewTCPSocket creates a TCP socket listener with the specified address and -// the specified tls configuration. If TLSConfig is set, will encapsulate the -// TCP listener inside a TLS one. -func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) { - l, err := net.Listen("tcp", addr) - if err != nil { - return nil, err - } - if tlsConfig != nil { - tlsConfig.NextProtos = []string{"http/1.1"} - l = tls.NewListener(l, tlsConfig) - } - return l, nil -} diff --git a/vendor/github.com/docker/go-connections/sockets/unix_socket.go b/vendor/github.com/docker/go-connections/sockets/unix_socket.go deleted file mode 100644 index a8b5dbb6fdc..00000000000 --- a/vendor/github.com/docker/go-connections/sockets/unix_socket.go +++ /dev/null @@ -1,32 +0,0 @@ -// +build !windows - -package sockets - -import ( - "net" - "os" - "syscall" -) - -// NewUnixSocket creates a unix socket with the specified path and group. -func NewUnixSocket(path string, gid int) (net.Listener, error) { - if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) { - return nil, err - } - mask := syscall.Umask(0777) - defer syscall.Umask(mask) - - l, err := net.Listen("unix", path) - if err != nil { - return nil, err - } - if err := os.Chown(path, 0, gid); err != nil { - l.Close() - return nil, err - } - if err := os.Chmod(path, 0660); err != nil { - l.Close() - return nil, err - } - return l, nil -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go b/vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go deleted file mode 100644 index 1ca0965e06e..00000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build go1.7 - -package tlsconfig - -import ( - "crypto/x509" - "runtime" -) - -// SystemCertPool returns a copy of the system cert pool, -// returns an error if failed to load or empty pool on windows. -func SystemCertPool() (*x509.CertPool, error) { - certpool, err := x509.SystemCertPool() - if err != nil && runtime.GOOS == "windows" { - return x509.NewCertPool(), nil - } - return certpool, err -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go b/vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go deleted file mode 100644 index 1ff81c333c3..00000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !go1.7 - -package tlsconfig - -import ( - "crypto/x509" -) - -// SystemCertPool returns an new empty cert pool, -// accessing system cert pool is supported in go 1.7 -func SystemCertPool() (*x509.CertPool, error) { - return x509.NewCertPool(), nil -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config.go b/vendor/github.com/docker/go-connections/tlsconfig/config.go deleted file mode 100644 index 0ef3fdcb469..00000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/config.go +++ /dev/null @@ -1,254 +0,0 @@ -// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. -// -// As a reminder from https://golang.org/pkg/crypto/tls/#Config: -// A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified. -// A Config may be reused; the tls package will also not modify it. -package tlsconfig - -import ( - "crypto/tls" - "crypto/x509" - "encoding/pem" - "fmt" - "io/ioutil" - "os" - - "github.com/pkg/errors" -) - -// Options represents the information needed to create client and server TLS configurations. -type Options struct { - CAFile string - - // If either CertFile or KeyFile is empty, Client() will not load them - // preventing the client from authenticating to the server. - // However, Server() requires them and will error out if they are empty. - CertFile string - KeyFile string - - // client-only option - InsecureSkipVerify bool - // server-only option - ClientAuth tls.ClientAuthType - // If ExclusiveRootPools is set, then if a CA file is provided, the root pool used for TLS - // creds will include exclusively the roots in that CA file. If no CA file is provided, - // the system pool will be used. - ExclusiveRootPools bool - MinVersion uint16 - // If Passphrase is set, it will be used to decrypt a TLS private key - // if the key is encrypted - Passphrase string -} - -// Extra (server-side) accepted CBC cipher suites - will phase out in the future -var acceptedCBCCiphers = []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, -} - -// DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls -// options struct but wants to use a commonly accepted set of TLS cipher suites, with -// known weak algorithms removed. -var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...) - -// allTLSVersions lists all the TLS versions and is used by the code that validates -// a uint16 value as a TLS version. -var allTLSVersions = map[uint16]struct{}{ - tls.VersionSSL30: {}, - tls.VersionTLS10: {}, - tls.VersionTLS11: {}, - tls.VersionTLS12: {}, -} - -// ServerDefault returns a secure-enough TLS configuration for the server TLS configuration. -func ServerDefault(ops ...func(*tls.Config)) *tls.Config { - tlsconfig := &tls.Config{ - // Avoid fallback by default to SSL protocols < TLS1.2 - MinVersion: tls.VersionTLS12, - PreferServerCipherSuites: true, - CipherSuites: DefaultServerAcceptedCiphers, - } - - for _, op := range ops { - op(tlsconfig) - } - - return tlsconfig -} - -// ClientDefault returns a secure-enough TLS configuration for the client TLS configuration. -func ClientDefault(ops ...func(*tls.Config)) *tls.Config { - tlsconfig := &tls.Config{ - // Prefer TLS1.2 as the client minimum - MinVersion: tls.VersionTLS12, - CipherSuites: clientCipherSuites, - } - - for _, op := range ops { - op(tlsconfig) - } - - return tlsconfig -} - -// certPool returns an X.509 certificate pool from `caFile`, the certificate file. -func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) { - // If we should verify the server, we need to load a trusted ca - var ( - certPool *x509.CertPool - err error - ) - if exclusivePool { - certPool = x509.NewCertPool() - } else { - certPool, err = SystemCertPool() - if err != nil { - return nil, fmt.Errorf("failed to read system certificates: %v", err) - } - } - pem, err := ioutil.ReadFile(caFile) - if err != nil { - return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err) - } - if !certPool.AppendCertsFromPEM(pem) { - return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile) - } - return certPool, nil -} - -// isValidMinVersion checks that the input value is a valid tls minimum version -func isValidMinVersion(version uint16) bool { - _, ok := allTLSVersions[version] - return ok -} - -// adjustMinVersion sets the MinVersion on `config`, the input configuration. -// It assumes the current MinVersion on the `config` is the lowest allowed. -func adjustMinVersion(options Options, config *tls.Config) error { - if options.MinVersion > 0 { - if !isValidMinVersion(options.MinVersion) { - return fmt.Errorf("Invalid minimum TLS version: %x", options.MinVersion) - } - if options.MinVersion < config.MinVersion { - return fmt.Errorf("Requested minimum TLS version is too low. Should be at-least: %x", config.MinVersion) - } - config.MinVersion = options.MinVersion - } - - return nil -} - -// IsErrEncryptedKey returns true if the 'err' is an error of incorrect -// password when tryin to decrypt a TLS private key -func IsErrEncryptedKey(err error) bool { - return errors.Cause(err) == x509.IncorrectPasswordError -} - -// getPrivateKey returns the private key in 'keyBytes', in PEM-encoded format. -// If the private key is encrypted, 'passphrase' is used to decrypted the -// private key. -func getPrivateKey(keyBytes []byte, passphrase string) ([]byte, error) { - // this section makes some small changes to code from notary/tuf/utils/x509.go - pemBlock, _ := pem.Decode(keyBytes) - if pemBlock == nil { - return nil, fmt.Errorf("no valid private key found") - } - - var err error - if x509.IsEncryptedPEMBlock(pemBlock) { - keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase)) - if err != nil { - return nil, errors.Wrap(err, "private key is encrypted, but could not decrypt it") - } - keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes}) - } - - return keyBytes, nil -} - -// getCert returns a Certificate from the CertFile and KeyFile in 'options', -// if the key is encrypted, the Passphrase in 'options' will be used to -// decrypt it. -func getCert(options Options) ([]tls.Certificate, error) { - if options.CertFile == "" && options.KeyFile == "" { - return nil, nil - } - - errMessage := "Could not load X509 key pair" - - cert, err := ioutil.ReadFile(options.CertFile) - if err != nil { - return nil, errors.Wrap(err, errMessage) - } - - prKeyBytes, err := ioutil.ReadFile(options.KeyFile) - if err != nil { - return nil, errors.Wrap(err, errMessage) - } - - prKeyBytes, err = getPrivateKey(prKeyBytes, options.Passphrase) - if err != nil { - return nil, errors.Wrap(err, errMessage) - } - - tlsCert, err := tls.X509KeyPair(cert, prKeyBytes) - if err != nil { - return nil, errors.Wrap(err, errMessage) - } - - return []tls.Certificate{tlsCert}, nil -} - -// Client returns a TLS configuration meant to be used by a client. -func Client(options Options) (*tls.Config, error) { - tlsConfig := ClientDefault() - tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify - if !options.InsecureSkipVerify && options.CAFile != "" { - CAs, err := certPool(options.CAFile, options.ExclusiveRootPools) - if err != nil { - return nil, err - } - tlsConfig.RootCAs = CAs - } - - tlsCerts, err := getCert(options) - if err != nil { - return nil, err - } - tlsConfig.Certificates = tlsCerts - - if err := adjustMinVersion(options, tlsConfig); err != nil { - return nil, err - } - - return tlsConfig, nil -} - -// Server returns a TLS configuration meant to be used by a server. -func Server(options Options) (*tls.Config, error) { - tlsConfig := ServerDefault() - tlsConfig.ClientAuth = options.ClientAuth - tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile) - if err != nil { - if os.IsNotExist(err) { - return nil, fmt.Errorf("Could not load X509 key pair (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err) - } - return nil, fmt.Errorf("Error reading X509 key pair (cert: %q, key: %q): %v. Make sure the key is not encrypted.", options.CertFile, options.KeyFile, err) - } - tlsConfig.Certificates = []tls.Certificate{tlsCert} - if options.ClientAuth >= tls.VerifyClientCertIfGiven && options.CAFile != "" { - CAs, err := certPool(options.CAFile, options.ExclusiveRootPools) - if err != nil { - return nil, err - } - tlsConfig.ClientCAs = CAs - } - - if err := adjustMinVersion(options, tlsConfig); err != nil { - return nil, err - } - - return tlsConfig, nil -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go b/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go deleted file mode 100644 index 6b4c6a7c0d0..00000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build go1.5 - -// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. -// -package tlsconfig - -import ( - "crypto/tls" -) - -// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set) -var clientCipherSuites = []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -} diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go b/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go deleted file mode 100644 index ee22df47cb2..00000000000 --- a/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build !go1.5 - -// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. -// -package tlsconfig - -import ( - "crypto/tls" -) - -// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set) -var clientCipherSuites = []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -} diff --git a/vendor/github.com/google/cadvisor/container/docker/client.go b/vendor/github.com/google/cadvisor/container/docker/client.go deleted file mode 100644 index 295e647cd74..00000000000 --- a/vendor/github.com/google/cadvisor/container/docker/client.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// 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. - -// Handler for /validate content. -// Validates cadvisor dependencies - kernel, os, docker setup. - -package docker - -import ( - "net/http" - "sync" - - dclient "github.com/docker/docker/client" - "github.com/docker/go-connections/tlsconfig" -) - -var ( - dockerClient *dclient.Client - dockerClientErr error - dockerClientOnce sync.Once -) - -// Client creates a Docker API client based on the given Docker flags -func Client() (*dclient.Client, error) { - dockerClientOnce.Do(func() { - var client *http.Client - if *ArgDockerTLS { - client = &http.Client{} - options := tlsconfig.Options{ - CAFile: *ArgDockerCA, - CertFile: *ArgDockerCert, - KeyFile: *ArgDockerKey, - InsecureSkipVerify: false, - } - tlsc, err := tlsconfig.Client(options) - if err != nil { - dockerClientErr = err - return - } - client.Transport = &http.Transport{ - TLSClientConfig: tlsc, - } - } - dockerClient, dockerClientErr = dclient.NewClientWithOpts( - dclient.WithHost(*ArgDockerEndpoint), - dclient.WithHTTPClient(client), - dclient.WithAPIVersionNegotiation()) - }) - return dockerClient, dockerClientErr -} diff --git a/vendor/github.com/google/cadvisor/container/docker/docker.go b/vendor/github.com/google/cadvisor/container/docker/docker.go deleted file mode 100644 index 05934bf9705..00000000000 --- a/vendor/github.com/google/cadvisor/container/docker/docker.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// 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. - -// Provides global docker information. -package docker - -import ( - "fmt" - "regexp" - "strconv" - - dockertypes "github.com/docker/docker/api/types" - "golang.org/x/net/context" - - "time" - - v1 "github.com/google/cadvisor/info/v1" - "github.com/google/cadvisor/machine" -) - -var dockerTimeout = 10 * time.Second - -func defaultContext() context.Context { - ctx, _ := context.WithTimeout(context.Background(), dockerTimeout) - return ctx -} - -func SetTimeout(timeout time.Duration) { - dockerTimeout = timeout -} - -func Status() (v1.DockerStatus, error) { - return StatusWithContext(defaultContext()) -} - -func StatusWithContext(ctx context.Context) (v1.DockerStatus, error) { - client, err := Client() - if err != nil { - return v1.DockerStatus{}, fmt.Errorf("unable to communicate with docker daemon: %v", err) - } - dockerInfo, err := client.Info(ctx) - if err != nil { - return v1.DockerStatus{}, err - } - return StatusFromDockerInfo(dockerInfo) -} - -func StatusFromDockerInfo(dockerInfo dockertypes.Info) (v1.DockerStatus, error) { - out := v1.DockerStatus{} - out.KernelVersion = machine.KernelVersion() - out.OS = dockerInfo.OperatingSystem - out.Hostname = dockerInfo.Name - out.RootDir = dockerInfo.DockerRootDir - out.Driver = dockerInfo.Driver - out.NumImages = dockerInfo.Images - out.NumContainers = dockerInfo.Containers - out.DriverStatus = make(map[string]string, len(dockerInfo.DriverStatus)) - for _, v := range dockerInfo.DriverStatus { - out.DriverStatus[v[0]] = v[1] - } - var err error - ver, err := VersionString() - if err != nil { - return out, err - } - out.Version = ver - ver, err = APIVersionString() - if err != nil { - return out, err - } - out.APIVersion = ver - return out, nil -} - -func Images() ([]v1.DockerImage, error) { - client, err := Client() - if err != nil { - return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err) - } - images, err := client.ImageList(defaultContext(), dockertypes.ImageListOptions{All: false}) - if err != nil { - return nil, err - } - - out := []v1.DockerImage{} - const unknownTag = ":" - for _, image := range images { - if len(image.RepoTags) == 1 && image.RepoTags[0] == unknownTag { - // images with repo or tags are uninteresting. - continue - } - di := v1.DockerImage{ - ID: image.ID, - RepoTags: image.RepoTags, - Created: image.Created, - VirtualSize: image.VirtualSize, - Size: image.Size, - } - out = append(out, di) - } - return out, nil - -} - -// Checks whether the dockerInfo reflects a valid docker setup, and returns it if it does, or an -// error otherwise. -func ValidateInfo() (*dockertypes.Info, error) { - client, err := Client() - if err != nil { - return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err) - } - - dockerInfo, err := client.Info(defaultContext()) - if err != nil { - return nil, fmt.Errorf("failed to detect Docker info: %v", err) - } - - // Fall back to version API if ServerVersion is not set in info. - if dockerInfo.ServerVersion == "" { - version, err := client.ServerVersion(defaultContext()) - if err != nil { - return nil, fmt.Errorf("unable to get docker version: %v", err) - } - dockerInfo.ServerVersion = version.Version - } - version, err := parseVersion(dockerInfo.ServerVersion, versionRe, 3) - if err != nil { - return nil, err - } - - if version[0] < 1 { - return nil, fmt.Errorf("cAdvisor requires docker version %v or above but we have found version %v reported as %q", []int{1, 0, 0}, version, dockerInfo.ServerVersion) - } - - if dockerInfo.Driver == "" { - return nil, fmt.Errorf("failed to find docker storage driver") - } - - return &dockerInfo, nil -} - -func APIVersion() ([]int, error) { - ver, err := APIVersionString() - if err != nil { - return nil, err - } - return parseVersion(ver, apiVersionRe, 2) -} - -func VersionString() (string, error) { - dockerVersion := "Unknown" - client, err := Client() - if err == nil { - version, err := client.ServerVersion(defaultContext()) - if err == nil { - dockerVersion = version.Version - } - } - return dockerVersion, err -} - -func APIVersionString() (string, error) { - apiVersion := "Unknown" - client, err := Client() - if err == nil { - version, err := client.ServerVersion(defaultContext()) - if err == nil { - apiVersion = version.APIVersion - } - } - return apiVersion, err -} - -func parseVersion(versionString string, regex *regexp.Regexp, length int) ([]int, error) { - matches := regex.FindAllStringSubmatch(versionString, -1) - if len(matches) != 1 { - return nil, fmt.Errorf("version string \"%v\" doesn't match expected regular expression: \"%v\"", versionString, regex.String()) - } - versionStringArray := matches[0][1:] - versionArray := make([]int, length) - for index, versionStr := range versionStringArray { - version, err := strconv.Atoi(versionStr) - if err != nil { - return nil, fmt.Errorf("error while parsing \"%v\" in \"%v\"", versionStr, versionString) - } - versionArray[index] = version - } - return versionArray, nil -} diff --git a/vendor/github.com/google/cadvisor/container/docker/factory.go b/vendor/github.com/google/cadvisor/container/docker/factory.go deleted file mode 100644 index 287563dac4d..00000000000 --- a/vendor/github.com/google/cadvisor/container/docker/factory.go +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package docker - -import ( - "flag" - "fmt" - "path" - "regexp" - "strconv" - "strings" - "sync" - "time" - - "github.com/blang/semver" - dockertypes "github.com/docker/docker/api/types" - - "github.com/google/cadvisor/container" - dockerutil "github.com/google/cadvisor/container/docker/utils" - "github.com/google/cadvisor/container/libcontainer" - "github.com/google/cadvisor/devicemapper" - "github.com/google/cadvisor/fs" - info "github.com/google/cadvisor/info/v1" - "github.com/google/cadvisor/machine" - "github.com/google/cadvisor/watcher" - "github.com/google/cadvisor/zfs" - - docker "github.com/docker/docker/client" - "golang.org/x/net/context" - "k8s.io/klog/v2" -) - -var ArgDockerEndpoint = flag.String("docker", "unix:///var/run/docker.sock", "docker endpoint") -var ArgDockerTLS = flag.Bool("docker-tls", false, "use TLS to connect to docker") -var ArgDockerCert = flag.String("docker-tls-cert", "cert.pem", "path to client certificate") -var ArgDockerKey = flag.String("docker-tls-key", "key.pem", "path to private key") -var ArgDockerCA = flag.String("docker-tls-ca", "ca.pem", "path to trusted CA") - -var dockerEnvMetadataWhiteList = flag.String("docker_env_metadata_whitelist", "", "DEPRECATED: this flag will be removed, please use `env_metadata_whitelist`. A comma-separated list of environment variable keys matched with specified prefix that needs to be collected for docker containers") - -// The namespace under which Docker aliases are unique. -const DockerNamespace = "docker" - -// The retry times for getting docker root dir -const rootDirRetries = 5 - -// The retry period for getting docker root dir, Millisecond -const rootDirRetryPeriod time.Duration = 1000 * time.Millisecond - -// Regexp that identifies docker cgroups, containers started with -// --cgroup-parent have another prefix than 'docker' -var dockerCgroupRegexp = regexp.MustCompile(`([a-z0-9]{64})`) - -var ( - // Basepath to all container specific information that libcontainer stores. - dockerRootDir string - - dockerRootDirFlag = flag.String("docker_root", "/var/lib/docker", "DEPRECATED: docker root is read from docker info (this is a fallback, default: /var/lib/docker)") - - dockerRootDirOnce sync.Once - - // flag that controls globally disabling thin_ls pending future enhancements. - // in production, it has been found that thin_ls makes excessive use of iops. - // in an iops restricted environment, usage of thin_ls must be controlled via blkio. - // pending that enhancement, disable its usage. - disableThinLs = true -) - -func RootDir() string { - dockerRootDirOnce.Do(func() { - for i := 0; i < rootDirRetries; i++ { - status, err := Status() - if err == nil && status.RootDir != "" { - dockerRootDir = status.RootDir - break - } else { - time.Sleep(rootDirRetryPeriod) - } - } - if dockerRootDir == "" { - dockerRootDir = *dockerRootDirFlag - } - }) - return dockerRootDir -} - -type storageDriver string - -const ( - devicemapperStorageDriver storageDriver = "devicemapper" - aufsStorageDriver storageDriver = "aufs" - overlayStorageDriver storageDriver = "overlay" - overlay2StorageDriver storageDriver = "overlay2" - zfsStorageDriver storageDriver = "zfs" - vfsStorageDriver storageDriver = "vfs" -) - -type dockerFactory struct { - machineInfoFactory info.MachineInfoFactory - - storageDriver storageDriver - storageDir string - - client *docker.Client - - // Information about the mounted cgroup subsystems. - cgroupSubsystems map[string]string - - // Information about mounted filesystems. - fsInfo fs.FsInfo - - dockerVersion []int - - dockerAPIVersion []int - - includedMetrics container.MetricSet - - thinPoolName string - thinPoolWatcher *devicemapper.ThinPoolWatcher - - zfsWatcher *zfs.ZfsWatcher -} - -func (f *dockerFactory) String() string { - return DockerNamespace -} - -func (f *dockerFactory) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (handler container.ContainerHandler, err error) { - client, err := Client() - if err != nil { - return - } - - dockerMetadataEnvAllowList := strings.Split(*dockerEnvMetadataWhiteList, ",") - - // prefer using the unified metadataEnvAllowList - if len(metadataEnvAllowList) != 0 { - dockerMetadataEnvAllowList = metadataEnvAllowList - } - - handler, err = newDockerContainerHandler( - client, - name, - f.machineInfoFactory, - f.fsInfo, - f.storageDriver, - f.storageDir, - f.cgroupSubsystems, - inHostNamespace, - dockerMetadataEnvAllowList, - f.dockerVersion, - f.includedMetrics, - f.thinPoolName, - f.thinPoolWatcher, - f.zfsWatcher, - ) - return -} - -// Returns the Docker ID from the full container name. -func ContainerNameToDockerId(name string) string { - id := path.Base(name) - - if matches := dockerCgroupRegexp.FindStringSubmatch(id); matches != nil { - return matches[1] - } - - return id -} - -// isContainerName returns true if the cgroup with associated name -// corresponds to a docker container. -func isContainerName(name string) bool { - // always ignore .mount cgroup even if associated with docker and delegate to systemd - if strings.HasSuffix(name, ".mount") { - return false - } - return dockerCgroupRegexp.MatchString(path.Base(name)) -} - -// Docker handles all containers under /docker -func (f *dockerFactory) CanHandleAndAccept(name string) (bool, bool, error) { - // if the container is not associated with docker, we can't handle it or accept it. - if !isContainerName(name) { - return false, false, nil - } - - // Check if the container is known to docker and it is active. - id := ContainerNameToDockerId(name) - - // We assume that if Inspect fails then the container is not known to docker. - ctnr, err := f.client.ContainerInspect(context.Background(), id) - if err != nil || !ctnr.State.Running { - return false, true, fmt.Errorf("error inspecting container: %v", err) - } - - return true, true, nil -} - -func (f *dockerFactory) DebugInfo() map[string][]string { - return map[string][]string{} -} - -var ( - versionRegexpString = `(\d+)\.(\d+)\.(\d+)` - versionRe = regexp.MustCompile(versionRegexpString) - apiVersionRegexpString = `(\d+)\.(\d+)` - apiVersionRe = regexp.MustCompile(apiVersionRegexpString) -) - -func startThinPoolWatcher(dockerInfo *dockertypes.Info) (*devicemapper.ThinPoolWatcher, error) { - _, err := devicemapper.ThinLsBinaryPresent() - if err != nil { - return nil, err - } - - if err := ensureThinLsKernelVersion(machine.KernelVersion()); err != nil { - return nil, err - } - - if disableThinLs { - return nil, fmt.Errorf("usage of thin_ls is disabled to preserve iops") - } - - dockerThinPoolName, err := dockerutil.DockerThinPoolName(*dockerInfo) - if err != nil { - return nil, err - } - - dockerMetadataDevice, err := dockerutil.DockerMetadataDevice(*dockerInfo) - if err != nil { - return nil, err - } - - thinPoolWatcher, err := devicemapper.NewThinPoolWatcher(dockerThinPoolName, dockerMetadataDevice) - if err != nil { - return nil, err - } - - go thinPoolWatcher.Start() - return thinPoolWatcher, nil -} - -func startZfsWatcher(dockerInfo *dockertypes.Info) (*zfs.ZfsWatcher, error) { - filesystem, err := dockerutil.DockerZfsFilesystem(*dockerInfo) - if err != nil { - return nil, err - } - - zfsWatcher, err := zfs.NewZfsWatcher(filesystem) - if err != nil { - return nil, err - } - - go zfsWatcher.Start() - return zfsWatcher, nil -} - -func ensureThinLsKernelVersion(kernelVersion string) error { - // kernel 4.4.0 has the proper bug fixes to allow thin_ls to work without corrupting the thin pool - minKernelVersion := semver.MustParse("4.4.0") - // RHEL 7 kernel 3.10.0 release >= 366 has the proper bug fixes backported from 4.4.0 to allow - // thin_ls to work without corrupting the thin pool - minRhel7KernelVersion := semver.MustParse("3.10.0") - - matches := versionRe.FindStringSubmatch(kernelVersion) - if len(matches) < 4 { - return fmt.Errorf("error parsing kernel version: %q is not a semver", kernelVersion) - } - - sem, err := semver.Make(matches[0]) - if err != nil { - return err - } - - if sem.GTE(minKernelVersion) { - // kernel 4.4+ - good - return nil - } - - // Certain RHEL/Centos 7.x kernels have a backport to fix the corruption bug - if !strings.Contains(kernelVersion, ".el7") { - // not a RHEL 7.x kernel - won't work - return fmt.Errorf("kernel version 4.4.0 or later is required to use thin_ls - you have %q", kernelVersion) - } - - // RHEL/Centos 7.x from here on - if sem.Major != 3 { - // only 3.x kernels *may* work correctly - return fmt.Errorf("RHEL/Centos 7.x kernel version 3.10.0-366 or later is required to use thin_ls - you have %q", kernelVersion) - } - - if sem.GT(minRhel7KernelVersion) { - // 3.10.1+ - good - return nil - } - - if sem.EQ(minRhel7KernelVersion) { - // need to check release - releaseRE := regexp.MustCompile(`^[^-]+-([0-9]+)\.`) - releaseMatches := releaseRE.FindStringSubmatch(kernelVersion) - if len(releaseMatches) != 2 { - return fmt.Errorf("unable to determine RHEL/Centos 7.x kernel release from %q", kernelVersion) - } - - release, err := strconv.Atoi(releaseMatches[1]) - if err != nil { - return fmt.Errorf("error parsing release %q: %v", releaseMatches[1], err) - } - - if release >= 366 { - return nil - } - } - - return fmt.Errorf("RHEL/Centos 7.x kernel version 3.10.0-366 or later is required to use thin_ls - you have %q", kernelVersion) -} - -// Register root container before running this function! -func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, includedMetrics container.MetricSet) error { - client, err := Client() - if err != nil { - return fmt.Errorf("unable to communicate with docker daemon: %v", err) - } - - dockerInfo, err := ValidateInfo() - if err != nil { - return fmt.Errorf("failed to validate Docker info: %v", err) - } - - // Version already validated above, assume no error here. - dockerVersion, _ := parseVersion(dockerInfo.ServerVersion, versionRe, 3) - - dockerAPIVersion, _ := APIVersion() - - cgroupSubsystems, err := libcontainer.GetCgroupSubsystems(includedMetrics) - if err != nil { - return fmt.Errorf("failed to get cgroup subsystems: %v", err) - } - - var ( - thinPoolWatcher *devicemapper.ThinPoolWatcher - thinPoolName string - zfsWatcher *zfs.ZfsWatcher - ) - if includedMetrics.Has(container.DiskUsageMetrics) { - if storageDriver(dockerInfo.Driver) == devicemapperStorageDriver { - thinPoolWatcher, err = startThinPoolWatcher(dockerInfo) - if err != nil { - klog.Errorf("devicemapper filesystem stats will not be reported: %v", err) - } - - // Safe to ignore error - driver status should always be populated. - status, _ := StatusFromDockerInfo(*dockerInfo) - thinPoolName = status.DriverStatus[dockerutil.DriverStatusPoolName] - } - - if storageDriver(dockerInfo.Driver) == zfsStorageDriver { - zfsWatcher, err = startZfsWatcher(dockerInfo) - if err != nil { - klog.Errorf("zfs filesystem stats will not be reported: %v", err) - } - } - } - - klog.V(1).Infof("Registering Docker factory") - f := &dockerFactory{ - cgroupSubsystems: cgroupSubsystems, - client: client, - dockerVersion: dockerVersion, - dockerAPIVersion: dockerAPIVersion, - fsInfo: fsInfo, - machineInfoFactory: factory, - storageDriver: storageDriver(dockerInfo.Driver), - storageDir: RootDir(), - includedMetrics: includedMetrics, - thinPoolName: thinPoolName, - thinPoolWatcher: thinPoolWatcher, - zfsWatcher: zfsWatcher, - } - - container.RegisterContainerHandlerFactory(f, []watcher.ContainerWatchSource{watcher.Raw}) - return nil -} diff --git a/vendor/github.com/google/cadvisor/container/docker/handler.go b/vendor/github.com/google/cadvisor/container/docker/handler.go deleted file mode 100644 index bfb8e381659..00000000000 --- a/vendor/github.com/google/cadvisor/container/docker/handler.go +++ /dev/null @@ -1,517 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// 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. - -// Handler for Docker containers. -package docker - -import ( - "fmt" - "io/ioutil" - "path" - "strconv" - "strings" - "time" - - "github.com/google/cadvisor/container" - "github.com/google/cadvisor/container/common" - dockerutil "github.com/google/cadvisor/container/docker/utils" - containerlibcontainer "github.com/google/cadvisor/container/libcontainer" - "github.com/google/cadvisor/devicemapper" - "github.com/google/cadvisor/fs" - info "github.com/google/cadvisor/info/v1" - "github.com/google/cadvisor/zfs" - "github.com/opencontainers/runc/libcontainer/cgroups" - - dockercontainer "github.com/docker/docker/api/types/container" - docker "github.com/docker/docker/client" - "golang.org/x/net/context" - "k8s.io/klog/v2" -) - -const ( - // The read write layers exist here. - aufsRWLayer = "diff" - overlayRWLayer = "upper" - overlay2RWLayer = "diff" - - // Path to the directory where docker stores log files if the json logging driver is enabled. - pathToContainersDir = "containers" -) - -type dockerContainerHandler struct { - // machineInfoFactory provides info.MachineInfo - machineInfoFactory info.MachineInfoFactory - - // Absolute path to the cgroup hierarchies of this container. - // (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test") - cgroupPaths map[string]string - - // the docker storage driver - storageDriver storageDriver - fsInfo fs.FsInfo - rootfsStorageDir string - - // Time at which this container was created. - creationTime time.Time - - // Metadata associated with the container. - envs map[string]string - labels map[string]string - - // Image name used for this container. - image string - - // The network mode of the container - networkMode dockercontainer.NetworkMode - - // Filesystem handler. - fsHandler common.FsHandler - - // The IP address of the container - ipAddress string - - includedMetrics container.MetricSet - - // the devicemapper poolname - poolName string - - // zfsParent is the parent for docker zfs - zfsParent string - - // Reference to the container - reference info.ContainerReference - - libcontainerHandler *containerlibcontainer.Handler -} - -var _ container.ContainerHandler = &dockerContainerHandler{} - -func getRwLayerID(containerID, storageDir string, sd storageDriver, dockerVersion []int) (string, error) { - const ( - // Docker version >=1.10.0 have a randomized ID for the root fs of a container. - randomizedRWLayerMinorVersion = 10 - rwLayerIDFile = "mount-id" - ) - if (dockerVersion[0] <= 1) && (dockerVersion[1] < randomizedRWLayerMinorVersion) { - return containerID, nil - } - - bytes, err := ioutil.ReadFile(path.Join(storageDir, "image", string(sd), "layerdb", "mounts", containerID, rwLayerIDFile)) - if err != nil { - return "", fmt.Errorf("failed to identify the read-write layer ID for container %q. - %v", containerID, err) - } - return string(bytes), err -} - -// newDockerContainerHandler returns a new container.ContainerHandler -func newDockerContainerHandler( - client *docker.Client, - name string, - machineInfoFactory info.MachineInfoFactory, - fsInfo fs.FsInfo, - storageDriver storageDriver, - storageDir string, - cgroupSubsystems map[string]string, - inHostNamespace bool, - metadataEnvAllowList []string, - dockerVersion []int, - includedMetrics container.MetricSet, - thinPoolName string, - thinPoolWatcher *devicemapper.ThinPoolWatcher, - zfsWatcher *zfs.ZfsWatcher, -) (container.ContainerHandler, error) { - // Create the cgroup paths. - cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems, name) - - // Generate the equivalent cgroup manager for this container. - cgroupManager, err := containerlibcontainer.NewCgroupManager(name, cgroupPaths) - if err != nil { - return nil, err - } - - rootFs := "/" - if !inHostNamespace { - rootFs = "/rootfs" - storageDir = path.Join(rootFs, storageDir) - } - - id := ContainerNameToDockerId(name) - - // Add the Containers dir where the log files are stored. - // FIXME: Give `otherStorageDir` a more descriptive name. - otherStorageDir := path.Join(storageDir, pathToContainersDir, id) - - rwLayerID, err := getRwLayerID(id, storageDir, storageDriver, dockerVersion) - if err != nil { - return nil, err - } - - // Determine the rootfs storage dir OR the pool name to determine the device. - // For devicemapper, we only need the thin pool name, and that is passed in to this call - var ( - rootfsStorageDir string - zfsFilesystem string - zfsParent string - ) - switch storageDriver { - case aufsStorageDriver: - rootfsStorageDir = path.Join(storageDir, string(aufsStorageDriver), aufsRWLayer, rwLayerID) - case overlayStorageDriver: - rootfsStorageDir = path.Join(storageDir, string(storageDriver), rwLayerID, overlayRWLayer) - case overlay2StorageDriver: - rootfsStorageDir = path.Join(storageDir, string(storageDriver), rwLayerID, overlay2RWLayer) - case vfsStorageDriver: - rootfsStorageDir = path.Join(storageDir) - case zfsStorageDriver: - status, err := Status() - if err != nil { - return nil, fmt.Errorf("unable to determine docker status: %v", err) - } - zfsParent = status.DriverStatus[dockerutil.DriverStatusParentDataset] - zfsFilesystem = path.Join(zfsParent, rwLayerID) - } - - // We assume that if Inspect fails then the container is not known to docker. - ctnr, err := client.ContainerInspect(context.Background(), id) - if err != nil { - return nil, fmt.Errorf("failed to inspect container %q: %v", id, err) - } - - // TODO: extract object mother method - handler := &dockerContainerHandler{ - machineInfoFactory: machineInfoFactory, - cgroupPaths: cgroupPaths, - fsInfo: fsInfo, - storageDriver: storageDriver, - poolName: thinPoolName, - rootfsStorageDir: rootfsStorageDir, - envs: make(map[string]string), - labels: ctnr.Config.Labels, - includedMetrics: includedMetrics, - zfsParent: zfsParent, - } - // Timestamp returned by Docker is in time.RFC3339Nano format. - handler.creationTime, err = time.Parse(time.RFC3339Nano, ctnr.Created) - if err != nil { - // This should not happen, report the error just in case - return nil, fmt.Errorf("failed to parse the create timestamp %q for container %q: %v", ctnr.Created, id, err) - } - handler.libcontainerHandler = containerlibcontainer.NewHandler(cgroupManager, rootFs, ctnr.State.Pid, includedMetrics) - - // Add the name and bare ID as aliases of the container. - handler.reference = info.ContainerReference{ - Id: id, - Name: name, - Aliases: []string{strings.TrimPrefix(ctnr.Name, "/"), id}, - Namespace: DockerNamespace, - } - handler.image = ctnr.Config.Image - handler.networkMode = ctnr.HostConfig.NetworkMode - // Only adds restartcount label if it's greater than 0 - if ctnr.RestartCount > 0 { - handler.labels["restartcount"] = strconv.Itoa(ctnr.RestartCount) - } - - // Obtain the IP address for the container. - // If the NetworkMode starts with 'container:' then we need to use the IP address of the container specified. - // This happens in cases such as kubernetes where the containers doesn't have an IP address itself and we need to use the pod's address - ipAddress := ctnr.NetworkSettings.IPAddress - networkMode := string(ctnr.HostConfig.NetworkMode) - if ipAddress == "" && strings.HasPrefix(networkMode, "container:") { - containerID := strings.TrimPrefix(networkMode, "container:") - c, err := client.ContainerInspect(context.Background(), containerID) - if err != nil { - return nil, fmt.Errorf("failed to inspect container %q: %v", id, err) - } - ipAddress = c.NetworkSettings.IPAddress - } - - handler.ipAddress = ipAddress - - if includedMetrics.Has(container.DiskUsageMetrics) { - handler.fsHandler = &dockerFsHandler{ - fsHandler: common.NewFsHandler(common.DefaultPeriod, rootfsStorageDir, otherStorageDir, fsInfo), - thinPoolWatcher: thinPoolWatcher, - zfsWatcher: zfsWatcher, - deviceID: ctnr.GraphDriver.Data["DeviceId"], - zfsFilesystem: zfsFilesystem, - } - } - - // split env vars to get metadata map. - for _, exposedEnv := range metadataEnvAllowList { - if exposedEnv == "" { - // if no dockerEnvWhitelist provided, len(metadataEnvAllowList) == 1, metadataEnvAllowList[0] == "" - continue - } - - for _, envVar := range ctnr.Config.Env { - if envVar != "" { - splits := strings.SplitN(envVar, "=", 2) - if len(splits) == 2 && strings.HasPrefix(splits[0], exposedEnv) { - handler.envs[strings.ToLower(splits[0])] = splits[1] - } - } - } - } - - return handler, nil -} - -// dockerFsHandler is a composite FsHandler implementation the incorporates -// the common fs handler, a devicemapper ThinPoolWatcher, and a zfsWatcher -type dockerFsHandler struct { - fsHandler common.FsHandler - - // thinPoolWatcher is the devicemapper thin pool watcher - thinPoolWatcher *devicemapper.ThinPoolWatcher - // deviceID is the id of the container's fs device - deviceID string - - // zfsWatcher is the zfs filesystem watcher - zfsWatcher *zfs.ZfsWatcher - // zfsFilesystem is the docker zfs filesystem - zfsFilesystem string -} - -var _ common.FsHandler = &dockerFsHandler{} - -func (h *dockerFsHandler) Start() { - h.fsHandler.Start() -} - -func (h *dockerFsHandler) Stop() { - h.fsHandler.Stop() -} - -func (h *dockerFsHandler) Usage() common.FsUsage { - usage := h.fsHandler.Usage() - - // When devicemapper is the storage driver, the base usage of the container comes from the thin pool. - // We still need the result of the fsHandler for any extra storage associated with the container. - // To correctly factor in the thin pool usage, we should: - // * Usage the thin pool usage as the base usage - // * Calculate the overall usage by adding the overall usage from the fs handler to the thin pool usage - if h.thinPoolWatcher != nil { - thinPoolUsage, err := h.thinPoolWatcher.GetUsage(h.deviceID) - if err != nil { - // TODO: ideally we should keep track of how many times we failed to get the usage for this - // device vs how many refreshes of the cache there have been, and display an error e.g. if we've - // had at least 1 refresh and we still can't find the device. - klog.V(5).Infof("unable to get fs usage from thin pool for device %s: %v", h.deviceID, err) - } else { - usage.BaseUsageBytes = thinPoolUsage - usage.TotalUsageBytes += thinPoolUsage - } - } - - if h.zfsWatcher != nil { - zfsUsage, err := h.zfsWatcher.GetUsage(h.zfsFilesystem) - if err != nil { - klog.V(5).Infof("unable to get fs usage from zfs for filesystem %s: %v", h.zfsFilesystem, err) - } else { - usage.BaseUsageBytes = zfsUsage - usage.TotalUsageBytes += zfsUsage - } - } - return usage -} - -func (h *dockerContainerHandler) Start() { - if h.fsHandler != nil { - h.fsHandler.Start() - } -} - -func (h *dockerContainerHandler) Cleanup() { - if h.fsHandler != nil { - h.fsHandler.Stop() - } -} - -func (h *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) { - return h.reference, nil -} - -func (h *dockerContainerHandler) needNet() bool { - if h.includedMetrics.Has(container.NetworkUsageMetrics) { - return !h.networkMode.IsContainer() - } - return false -} - -func (h *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) { - hasFilesystem := h.includedMetrics.Has(container.DiskUsageMetrics) - spec, err := common.GetSpec(h.cgroupPaths, h.machineInfoFactory, h.needNet(), hasFilesystem) - - spec.Labels = h.labels - spec.Envs = h.envs - spec.Image = h.image - spec.CreationTime = h.creationTime - - return spec, err -} - -func (h *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error { - mi, err := h.machineInfoFactory.GetMachineInfo() - if err != nil { - return err - } - - if h.includedMetrics.Has(container.DiskIOMetrics) { - common.AssignDeviceNamesToDiskStats((*common.MachineInfoNamer)(mi), &stats.DiskIo) - } - - if !h.includedMetrics.Has(container.DiskUsageMetrics) { - return nil - } - var device string - switch h.storageDriver { - case devicemapperStorageDriver: - // Device has to be the pool name to correlate with the device name as - // set in the machine info filesystems. - device = h.poolName - case aufsStorageDriver, overlayStorageDriver, overlay2StorageDriver, vfsStorageDriver: - deviceInfo, err := h.fsInfo.GetDirFsDevice(h.rootfsStorageDir) - if err != nil { - return fmt.Errorf("unable to determine device info for dir: %v: %v", h.rootfsStorageDir, err) - } - device = deviceInfo.Device - case zfsStorageDriver: - device = h.zfsParent - default: - return nil - } - - var ( - limit uint64 - fsType string - ) - - var fsInfo *info.FsInfo - - // Docker does not impose any filesystem limits for containers. So use capacity as limit. - for _, fs := range mi.Filesystems { - if fs.Device == device { - limit = fs.Capacity - fsType = fs.Type - fsInfo = &fs - break - } - } - - fsStat := info.FsStats{Device: device, Type: fsType, Limit: limit} - usage := h.fsHandler.Usage() - fsStat.BaseUsage = usage.BaseUsageBytes - fsStat.Usage = usage.TotalUsageBytes - fsStat.Inodes = usage.InodeUsage - - if fsInfo != nil { - fileSystems, err := h.fsInfo.GetGlobalFsInfo() - - if err == nil { - addDiskStats(fileSystems, fsInfo, &fsStat) - } else { - klog.Errorf("Unable to obtain diskstats for filesystem %s: %v", fsStat.Device, err) - } - } - - stats.Filesystem = append(stats.Filesystem, fsStat) - - return nil -} - -func addDiskStats(fileSystems []fs.Fs, fsInfo *info.FsInfo, fsStats *info.FsStats) { - if fsInfo == nil { - return - } - - for _, fileSys := range fileSystems { - if fsInfo.DeviceMajor == fileSys.DiskStats.Major && - fsInfo.DeviceMinor == fileSys.DiskStats.Minor { - fsStats.ReadsCompleted = fileSys.DiskStats.ReadsCompleted - fsStats.ReadsMerged = fileSys.DiskStats.ReadsMerged - fsStats.SectorsRead = fileSys.DiskStats.SectorsRead - fsStats.ReadTime = fileSys.DiskStats.ReadTime - fsStats.WritesCompleted = fileSys.DiskStats.WritesCompleted - fsStats.WritesMerged = fileSys.DiskStats.WritesMerged - fsStats.SectorsWritten = fileSys.DiskStats.SectorsWritten - fsStats.WriteTime = fileSys.DiskStats.WriteTime - fsStats.IoInProgress = fileSys.DiskStats.IoInProgress - fsStats.IoTime = fileSys.DiskStats.IoTime - fsStats.WeightedIoTime = fileSys.DiskStats.WeightedIoTime - break - } - } -} - -// TODO(vmarmol): Get from libcontainer API instead of cgroup manager when we don't have to support older Dockers. -func (h *dockerContainerHandler) GetStats() (*info.ContainerStats, error) { - stats, err := h.libcontainerHandler.GetStats() - if err != nil { - return stats, err - } - // Clean up stats for containers that don't have their own network - this - // includes containers running in Kubernetes pods that use the network of the - // infrastructure container. This stops metrics being reported multiple times - // for each container in a pod. - if !h.needNet() { - stats.Network = info.NetworkStats{} - } - - // Get filesystem stats. - err = h.getFsStats(stats) - if err != nil { - return stats, err - } - - return stats, nil -} - -func (h *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) { - // No-op for Docker driver. - return []info.ContainerReference{}, nil -} - -func (h *dockerContainerHandler) GetCgroupPath(resource string) (string, error) { - var res string - if !cgroups.IsCgroup2UnifiedMode() { - res = resource - } - path, ok := h.cgroupPaths[res] - if !ok { - return "", fmt.Errorf("could not find path for resource %q for container %q", resource, h.reference.Name) - } - return path, nil -} - -func (h *dockerContainerHandler) GetContainerLabels() map[string]string { - return h.labels -} - -func (h *dockerContainerHandler) GetContainerIPAddress() string { - return h.ipAddress -} - -func (h *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { - return h.libcontainerHandler.GetProcesses() -} - -func (h *dockerContainerHandler) Exists() bool { - return common.CgroupExists(h.cgroupPaths) -} - -func (h *dockerContainerHandler) Type() container.ContainerType { - return container.ContainerTypeDocker -} diff --git a/vendor/github.com/google/cadvisor/container/docker/install/install.go b/vendor/github.com/google/cadvisor/container/docker/install/install.go deleted file mode 100644 index 81346f68806..00000000000 --- a/vendor/github.com/google/cadvisor/container/docker/install/install.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 Google Inc. All Rights Reserved. -// -// 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. - -// The install package registers docker.NewPlugin() as the "docker" container provider when imported -package install - -import ( - "k8s.io/klog/v2" - - "github.com/google/cadvisor/container" - "github.com/google/cadvisor/container/docker" -) - -func init() { - err := container.RegisterPlugin("docker", docker.NewPlugin()) - if err != nil { - klog.Fatalf("Failed to register docker plugin: %v", err) - } -} diff --git a/vendor/github.com/google/cadvisor/container/docker/plugin.go b/vendor/github.com/google/cadvisor/container/docker/plugin.go deleted file mode 100644 index 07e471a732f..00000000000 --- a/vendor/github.com/google/cadvisor/container/docker/plugin.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package docker - -import ( - "time" - - "golang.org/x/net/context" - "k8s.io/klog/v2" - - "github.com/google/cadvisor/container" - "github.com/google/cadvisor/fs" - info "github.com/google/cadvisor/info/v1" - "github.com/google/cadvisor/watcher" -) - -const dockerClientTimeout = 10 * time.Second - -// NewPlugin returns an implementation of container.Plugin suitable for passing to container.RegisterPlugin() -func NewPlugin() container.Plugin { - return &plugin{} -} - -type plugin struct{} - -func (p *plugin) InitializeFSContext(context *fs.Context) error { - SetTimeout(dockerClientTimeout) - // Try to connect to docker indefinitely on startup. - dockerStatus := retryDockerStatus() - context.Docker = fs.DockerContext{ - Root: RootDir(), - Driver: dockerStatus.Driver, - DriverStatus: dockerStatus.DriverStatus, - } - return nil -} - -func (p *plugin) Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, includedMetrics container.MetricSet) (watcher.ContainerWatcher, error) { - err := Register(factory, fsInfo, includedMetrics) - return nil, err -} - -func retryDockerStatus() info.DockerStatus { - startupTimeout := dockerClientTimeout - maxTimeout := 4 * startupTimeout - for { - ctx, _ := context.WithTimeout(context.Background(), startupTimeout) - dockerStatus, err := StatusWithContext(ctx) - if err == nil { - return dockerStatus - } - - switch err { - case context.DeadlineExceeded: - klog.Warningf("Timeout trying to communicate with docker during initialization, will retry") - default: - klog.V(5).Infof("Docker not connected: %v", err) - return info.DockerStatus{} - } - - startupTimeout = 2 * startupTimeout - if startupTimeout > maxTimeout { - startupTimeout = maxTimeout - } - } -} diff --git a/vendor/github.com/google/cadvisor/container/docker/utils/docker.go b/vendor/github.com/google/cadvisor/container/docker/utils/docker.go deleted file mode 100644 index 658607f7368..00000000000 --- a/vendor/github.com/google/cadvisor/container/docker/utils/docker.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "fmt" - "os" - "strings" - - dockertypes "github.com/docker/docker/api/types" -) - -const ( - DriverStatusPoolName = "Pool Name" - DriverStatusMetadataFile = "Metadata file" - DriverStatusParentDataset = "Parent Dataset" -) - -func DriverStatusValue(status [][2]string, target string) string { - for _, v := range status { - if strings.EqualFold(v[0], target) { - return v[1] - } - } - - return "" -} - -func DockerThinPoolName(info dockertypes.Info) (string, error) { - poolName := DriverStatusValue(info.DriverStatus, DriverStatusPoolName) - if len(poolName) == 0 { - return "", fmt.Errorf("Could not get devicemapper pool name") - } - - return poolName, nil -} - -func DockerMetadataDevice(info dockertypes.Info) (string, error) { - metadataDevice := DriverStatusValue(info.DriverStatus, DriverStatusMetadataFile) - if len(metadataDevice) != 0 { - return metadataDevice, nil - } - - poolName, err := DockerThinPoolName(info) - if err != nil { - return "", err - } - - metadataDevice = fmt.Sprintf("/dev/mapper/%s_tmeta", poolName) - - if _, err := os.Stat(metadataDevice); err != nil { - return "", err - } - - return metadataDevice, nil -} - -func DockerZfsFilesystem(info dockertypes.Info) (string, error) { - filesystem := DriverStatusValue(info.DriverStatus, DriverStatusParentDataset) - if len(filesystem) == 0 { - return "", fmt.Errorf("Could not get zfs filesystem") - } - - return filesystem, nil -} diff --git a/vendor/github.com/google/cadvisor/zfs/watcher.go b/vendor/github.com/google/cadvisor/zfs/watcher.go deleted file mode 100644 index ace42853857..00000000000 --- a/vendor/github.com/google/cadvisor/zfs/watcher.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -package zfs - -import ( - "fmt" - "sync" - "time" - - zfs "github.com/mistifyio/go-zfs" - "k8s.io/klog/v2" -) - -// zfsWatcher maintains a cache of filesystem -> usage stats for a -// zfs filesystem -type ZfsWatcher struct { - filesystem string - lock *sync.RWMutex - cache map[string]uint64 - period time.Duration - stopChan chan struct{} -} - -// NewThinPoolWatcher returns a new ThinPoolWatcher for the given devicemapper -// thin pool name and metadata device or an error. -func NewZfsWatcher(filesystem string) (*ZfsWatcher, error) { - - return &ZfsWatcher{ - filesystem: filesystem, - lock: &sync.RWMutex{}, - cache: make(map[string]uint64), - period: 15 * time.Second, - stopChan: make(chan struct{}), - }, nil -} - -// Start starts the ZfsWatcher. -func (w *ZfsWatcher) Start() { - err := w.Refresh() - if err != nil { - klog.Errorf("encountered error refreshing zfs watcher: %v", err) - } - - for { - select { - case <-w.stopChan: - return - case <-time.After(w.period): - start := time.Now() - err = w.Refresh() - if err != nil { - klog.Errorf("encountered error refreshing zfs watcher: %v", err) - } - - // print latency for refresh - duration := time.Since(start) - klog.V(5).Infof("zfs(%d) took %s", start.Unix(), duration) - } - } -} - -// Stop stops the ZfsWatcher. -func (w *ZfsWatcher) Stop() { - close(w.stopChan) -} - -// GetUsage gets the cached usage value of the given filesystem. -func (w *ZfsWatcher) GetUsage(filesystem string) (uint64, error) { - w.lock.RLock() - defer w.lock.RUnlock() - - v, ok := w.cache[filesystem] - if !ok { - return 0, fmt.Errorf("no cached value for usage of filesystem %v", filesystem) - } - - return v, nil -} - -// Refresh performs a zfs get -func (w *ZfsWatcher) Refresh() error { - w.lock.Lock() - defer w.lock.Unlock() - newCache := make(map[string]uint64) - parent, err := zfs.GetDataset(w.filesystem) - if err != nil { - klog.Errorf("encountered error getting zfs filesystem: %s: %v", w.filesystem, err) - return err - } - children, err := parent.Children(0) - if err != nil { - klog.Errorf("encountered error getting children of zfs filesystem: %s: %v", w.filesystem, err) - return err - } - - for _, ds := range children { - newCache[ds.Name] = ds.Used - } - - w.cache = newCache - return nil -} diff --git a/vendor/github.com/morikuni/aec/LICENSE b/vendor/github.com/morikuni/aec/LICENSE deleted file mode 100644 index 1c264016419..00000000000 --- a/vendor/github.com/morikuni/aec/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Taihei Morikuni - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/morikuni/aec/README.md b/vendor/github.com/morikuni/aec/README.md deleted file mode 100644 index 3cbc4343ee2..00000000000 --- a/vendor/github.com/morikuni/aec/README.md +++ /dev/null @@ -1,178 +0,0 @@ -# aec - -[![GoDoc](https://godoc.org/github.com/morikuni/aec?status.svg)](https://godoc.org/github.com/morikuni/aec) - -Go wrapper for ANSI escape code. - -## Install - -```bash -go get github.com/morikuni/aec -``` - -## Features - -ANSI escape codes depend on terminal environment. -Some of these features may not work. -Check supported Font-Style/Font-Color features with [checkansi](./checkansi). - -[Wikipedia](https://en.wikipedia.org/wiki/ANSI_escape_code) for more detail. - -### Cursor - -- `Up(n)` -- `Down(n)` -- `Right(n)` -- `Left(n)` -- `NextLine(n)` -- `PreviousLine(n)` -- `Column(col)` -- `Position(row, col)` -- `Save` -- `Restore` -- `Hide` -- `Show` -- `Report` - -### Erase - -- `EraseDisplay(mode)` -- `EraseLine(mode)` - -### Scroll - -- `ScrollUp(n)` -- `ScrollDown(n)` - -### Font Style - -- `Bold` -- `Faint` -- `Italic` -- `Underline` -- `BlinkSlow` -- `BlinkRapid` -- `Inverse` -- `Conceal` -- `CrossOut` -- `Frame` -- `Encircle` -- `Overline` - -### Font Color - -Foreground color. - -- `DefaultF` -- `BlackF` -- `RedF` -- `GreenF` -- `YellowF` -- `BlueF` -- `MagentaF` -- `CyanF` -- `WhiteF` -- `LightBlackF` -- `LightRedF` -- `LightGreenF` -- `LightYellowF` -- `LightBlueF` -- `LightMagentaF` -- `LightCyanF` -- `LightWhiteF` -- `Color3BitF(color)` -- `Color8BitF(color)` -- `FullColorF(r, g, b)` - -Background color. - -- `DefaultB` -- `BlackB` -- `RedB` -- `GreenB` -- `YellowB` -- `BlueB` -- `MagentaB` -- `CyanB` -- `WhiteB` -- `LightBlackB` -- `LightRedB` -- `LightGreenB` -- `LightYellowB` -- `LightBlueB` -- `LightMagentaB` -- `LightCyanB` -- `LightWhiteB` -- `Color3BitB(color)` -- `Color8BitB(color)` -- `FullColorB(r, g, b)` - -### Color Converter - -24bit RGB color to ANSI color. - -- `NewRGB3Bit(r, g, b)` -- `NewRGB8Bit(r, g, b)` - -### Builder - -To mix these features. - -```go -custom := aec.EmptyBuilder.Right(2).RGB8BitF(128, 255, 64).RedB().ANSI -custom.Apply("Hello World") -``` - -## Usage - -1. Create ANSI by `aec.XXX().With(aec.YYY())` or `aec.EmptyBuilder.XXX().YYY().ANSI` -2. Print ANSI by `fmt.Print(ansi, "some string", aec.Reset)` or `fmt.Print(ansi.Apply("some string"))` - -`aec.Reset` should be added when using font style or font color features. - -## Example - -Simple progressbar. - -![sample](./sample.gif) - -```go -package main - -import ( - "fmt" - "strings" - "time" - - "github.com/morikuni/aec" -) - -func main() { - const n = 20 - builder := aec.EmptyBuilder - - up2 := aec.Up(2) - col := aec.Column(n + 2) - bar := aec.Color8BitF(aec.NewRGB8Bit(64, 255, 64)) - label := builder.LightRedF().Underline().With(col).Right(1).ANSI - - // for up2 - fmt.Println() - fmt.Println() - - for i := 0; i <= n; i++ { - fmt.Print(up2) - fmt.Println(label.Apply(fmt.Sprint(i, "/", n))) - fmt.Print("[") - fmt.Print(bar.Apply(strings.Repeat("=", i))) - fmt.Println(col.Apply("]")) - time.Sleep(100 * time.Millisecond) - } -} -``` - -## License - -[MIT](./LICENSE) - - diff --git a/vendor/github.com/morikuni/aec/aec.go b/vendor/github.com/morikuni/aec/aec.go deleted file mode 100644 index 566be6eb1ef..00000000000 --- a/vendor/github.com/morikuni/aec/aec.go +++ /dev/null @@ -1,137 +0,0 @@ -package aec - -import "fmt" - -// EraseMode is listed in a variable EraseModes. -type EraseMode uint - -var ( - // EraseModes is a list of EraseMode. - EraseModes struct { - // All erase all. - All EraseMode - - // Head erase to head. - Head EraseMode - - // Tail erase to tail. - Tail EraseMode - } - - // Save saves the cursor position. - Save ANSI - - // Restore restores the cursor position. - Restore ANSI - - // Hide hides the cursor. - Hide ANSI - - // Show shows the cursor. - Show ANSI - - // Report reports the cursor position. - Report ANSI -) - -// Up moves up the cursor. -func Up(n uint) ANSI { - if n == 0 { - return empty - } - return newAnsi(fmt.Sprintf(esc+"%dA", n)) -} - -// Down moves down the cursor. -func Down(n uint) ANSI { - if n == 0 { - return empty - } - return newAnsi(fmt.Sprintf(esc+"%dB", n)) -} - -// Right moves right the cursor. -func Right(n uint) ANSI { - if n == 0 { - return empty - } - return newAnsi(fmt.Sprintf(esc+"%dC", n)) -} - -// Left moves left the cursor. -func Left(n uint) ANSI { - if n == 0 { - return empty - } - return newAnsi(fmt.Sprintf(esc+"%dD", n)) -} - -// NextLine moves down the cursor to head of a line. -func NextLine(n uint) ANSI { - if n == 0 { - return empty - } - return newAnsi(fmt.Sprintf(esc+"%dE", n)) -} - -// PreviousLine moves up the cursor to head of a line. -func PreviousLine(n uint) ANSI { - if n == 0 { - return empty - } - return newAnsi(fmt.Sprintf(esc+"%dF", n)) -} - -// Column set the cursor position to a given column. -func Column(col uint) ANSI { - return newAnsi(fmt.Sprintf(esc+"%dG", col)) -} - -// Position set the cursor position to a given absolute position. -func Position(row, col uint) ANSI { - return newAnsi(fmt.Sprintf(esc+"%d;%dH", row, col)) -} - -// EraseDisplay erases display by given EraseMode. -func EraseDisplay(m EraseMode) ANSI { - return newAnsi(fmt.Sprintf(esc+"%dJ", m)) -} - -// EraseLine erases lines by given EraseMode. -func EraseLine(m EraseMode) ANSI { - return newAnsi(fmt.Sprintf(esc+"%dK", m)) -} - -// ScrollUp scrolls up the page. -func ScrollUp(n int) ANSI { - if n == 0 { - return empty - } - return newAnsi(fmt.Sprintf(esc+"%dS", n)) -} - -// ScrollDown scrolls down the page. -func ScrollDown(n int) ANSI { - if n == 0 { - return empty - } - return newAnsi(fmt.Sprintf(esc+"%dT", n)) -} - -func init() { - EraseModes = struct { - All EraseMode - Head EraseMode - Tail EraseMode - }{ - Tail: 0, - Head: 1, - All: 2, - } - - Save = newAnsi(esc + "s") - Restore = newAnsi(esc + "u") - Hide = newAnsi(esc + "?25l") - Show = newAnsi(esc + "?25h") - Report = newAnsi(esc + "6n") -} diff --git a/vendor/github.com/morikuni/aec/ansi.go b/vendor/github.com/morikuni/aec/ansi.go deleted file mode 100644 index e60722e6e60..00000000000 --- a/vendor/github.com/morikuni/aec/ansi.go +++ /dev/null @@ -1,59 +0,0 @@ -package aec - -import ( - "fmt" - "strings" -) - -const esc = "\x1b[" - -// Reset resets SGR effect. -const Reset string = "\x1b[0m" - -var empty = newAnsi("") - -// ANSI represents ANSI escape code. -type ANSI interface { - fmt.Stringer - - // With adapts given ANSIs. - With(...ANSI) ANSI - - // Apply wraps given string in ANSI. - Apply(string) string -} - -type ansiImpl string - -func newAnsi(s string) *ansiImpl { - r := ansiImpl(s) - return &r -} - -func (a *ansiImpl) With(ansi ...ANSI) ANSI { - return concat(append([]ANSI{a}, ansi...)) -} - -func (a *ansiImpl) Apply(s string) string { - return a.String() + s + Reset -} - -func (a *ansiImpl) String() string { - return string(*a) -} - -// Apply wraps given string in ANSIs. -func Apply(s string, ansi ...ANSI) string { - if len(ansi) == 0 { - return s - } - return concat(ansi).Apply(s) -} - -func concat(ansi []ANSI) ANSI { - strs := make([]string, 0, len(ansi)) - for _, p := range ansi { - strs = append(strs, p.String()) - } - return newAnsi(strings.Join(strs, "")) -} diff --git a/vendor/github.com/morikuni/aec/builder.go b/vendor/github.com/morikuni/aec/builder.go deleted file mode 100644 index 13bd002d4e3..00000000000 --- a/vendor/github.com/morikuni/aec/builder.go +++ /dev/null @@ -1,388 +0,0 @@ -package aec - -// Builder is a lightweight syntax to construct customized ANSI. -type Builder struct { - ANSI ANSI -} - -// EmptyBuilder is an initialized Builder. -var EmptyBuilder *Builder - -// NewBuilder creates a Builder from existing ANSI. -func NewBuilder(a ...ANSI) *Builder { - return &Builder{concat(a)} -} - -// With is a syntax for With. -func (builder *Builder) With(a ...ANSI) *Builder { - return NewBuilder(builder.ANSI.With(a...)) -} - -// Up is a syntax for Up. -func (builder *Builder) Up(n uint) *Builder { - return builder.With(Up(n)) -} - -// Down is a syntax for Down. -func (builder *Builder) Down(n uint) *Builder { - return builder.With(Down(n)) -} - -// Right is a syntax for Right. -func (builder *Builder) Right(n uint) *Builder { - return builder.With(Right(n)) -} - -// Left is a syntax for Left. -func (builder *Builder) Left(n uint) *Builder { - return builder.With(Left(n)) -} - -// NextLine is a syntax for NextLine. -func (builder *Builder) NextLine(n uint) *Builder { - return builder.With(NextLine(n)) -} - -// PreviousLine is a syntax for PreviousLine. -func (builder *Builder) PreviousLine(n uint) *Builder { - return builder.With(PreviousLine(n)) -} - -// Column is a syntax for Column. -func (builder *Builder) Column(col uint) *Builder { - return builder.With(Column(col)) -} - -// Position is a syntax for Position. -func (builder *Builder) Position(row, col uint) *Builder { - return builder.With(Position(row, col)) -} - -// EraseDisplay is a syntax for EraseDisplay. -func (builder *Builder) EraseDisplay(m EraseMode) *Builder { - return builder.With(EraseDisplay(m)) -} - -// EraseLine is a syntax for EraseLine. -func (builder *Builder) EraseLine(m EraseMode) *Builder { - return builder.With(EraseLine(m)) -} - -// ScrollUp is a syntax for ScrollUp. -func (builder *Builder) ScrollUp(n int) *Builder { - return builder.With(ScrollUp(n)) -} - -// ScrollDown is a syntax for ScrollDown. -func (builder *Builder) ScrollDown(n int) *Builder { - return builder.With(ScrollDown(n)) -} - -// Save is a syntax for Save. -func (builder *Builder) Save() *Builder { - return builder.With(Save) -} - -// Restore is a syntax for Restore. -func (builder *Builder) Restore() *Builder { - return builder.With(Restore) -} - -// Hide is a syntax for Hide. -func (builder *Builder) Hide() *Builder { - return builder.With(Hide) -} - -// Show is a syntax for Show. -func (builder *Builder) Show() *Builder { - return builder.With(Show) -} - -// Report is a syntax for Report. -func (builder *Builder) Report() *Builder { - return builder.With(Report) -} - -// Bold is a syntax for Bold. -func (builder *Builder) Bold() *Builder { - return builder.With(Bold) -} - -// Faint is a syntax for Faint. -func (builder *Builder) Faint() *Builder { - return builder.With(Faint) -} - -// Italic is a syntax for Italic. -func (builder *Builder) Italic() *Builder { - return builder.With(Italic) -} - -// Underline is a syntax for Underline. -func (builder *Builder) Underline() *Builder { - return builder.With(Underline) -} - -// BlinkSlow is a syntax for BlinkSlow. -func (builder *Builder) BlinkSlow() *Builder { - return builder.With(BlinkSlow) -} - -// BlinkRapid is a syntax for BlinkRapid. -func (builder *Builder) BlinkRapid() *Builder { - return builder.With(BlinkRapid) -} - -// Inverse is a syntax for Inverse. -func (builder *Builder) Inverse() *Builder { - return builder.With(Inverse) -} - -// Conceal is a syntax for Conceal. -func (builder *Builder) Conceal() *Builder { - return builder.With(Conceal) -} - -// CrossOut is a syntax for CrossOut. -func (builder *Builder) CrossOut() *Builder { - return builder.With(CrossOut) -} - -// BlackF is a syntax for BlackF. -func (builder *Builder) BlackF() *Builder { - return builder.With(BlackF) -} - -// RedF is a syntax for RedF. -func (builder *Builder) RedF() *Builder { - return builder.With(RedF) -} - -// GreenF is a syntax for GreenF. -func (builder *Builder) GreenF() *Builder { - return builder.With(GreenF) -} - -// YellowF is a syntax for YellowF. -func (builder *Builder) YellowF() *Builder { - return builder.With(YellowF) -} - -// BlueF is a syntax for BlueF. -func (builder *Builder) BlueF() *Builder { - return builder.With(BlueF) -} - -// MagentaF is a syntax for MagentaF. -func (builder *Builder) MagentaF() *Builder { - return builder.With(MagentaF) -} - -// CyanF is a syntax for CyanF. -func (builder *Builder) CyanF() *Builder { - return builder.With(CyanF) -} - -// WhiteF is a syntax for WhiteF. -func (builder *Builder) WhiteF() *Builder { - return builder.With(WhiteF) -} - -// DefaultF is a syntax for DefaultF. -func (builder *Builder) DefaultF() *Builder { - return builder.With(DefaultF) -} - -// BlackB is a syntax for BlackB. -func (builder *Builder) BlackB() *Builder { - return builder.With(BlackB) -} - -// RedB is a syntax for RedB. -func (builder *Builder) RedB() *Builder { - return builder.With(RedB) -} - -// GreenB is a syntax for GreenB. -func (builder *Builder) GreenB() *Builder { - return builder.With(GreenB) -} - -// YellowB is a syntax for YellowB. -func (builder *Builder) YellowB() *Builder { - return builder.With(YellowB) -} - -// BlueB is a syntax for BlueB. -func (builder *Builder) BlueB() *Builder { - return builder.With(BlueB) -} - -// MagentaB is a syntax for MagentaB. -func (builder *Builder) MagentaB() *Builder { - return builder.With(MagentaB) -} - -// CyanB is a syntax for CyanB. -func (builder *Builder) CyanB() *Builder { - return builder.With(CyanB) -} - -// WhiteB is a syntax for WhiteB. -func (builder *Builder) WhiteB() *Builder { - return builder.With(WhiteB) -} - -// DefaultB is a syntax for DefaultB. -func (builder *Builder) DefaultB() *Builder { - return builder.With(DefaultB) -} - -// Frame is a syntax for Frame. -func (builder *Builder) Frame() *Builder { - return builder.With(Frame) -} - -// Encircle is a syntax for Encircle. -func (builder *Builder) Encircle() *Builder { - return builder.With(Encircle) -} - -// Overline is a syntax for Overline. -func (builder *Builder) Overline() *Builder { - return builder.With(Overline) -} - -// LightBlackF is a syntax for LightBlueF. -func (builder *Builder) LightBlackF() *Builder { - return builder.With(LightBlackF) -} - -// LightRedF is a syntax for LightRedF. -func (builder *Builder) LightRedF() *Builder { - return builder.With(LightRedF) -} - -// LightGreenF is a syntax for LightGreenF. -func (builder *Builder) LightGreenF() *Builder { - return builder.With(LightGreenF) -} - -// LightYellowF is a syntax for LightYellowF. -func (builder *Builder) LightYellowF() *Builder { - return builder.With(LightYellowF) -} - -// LightBlueF is a syntax for LightBlueF. -func (builder *Builder) LightBlueF() *Builder { - return builder.With(LightBlueF) -} - -// LightMagentaF is a syntax for LightMagentaF. -func (builder *Builder) LightMagentaF() *Builder { - return builder.With(LightMagentaF) -} - -// LightCyanF is a syntax for LightCyanF. -func (builder *Builder) LightCyanF() *Builder { - return builder.With(LightCyanF) -} - -// LightWhiteF is a syntax for LightWhiteF. -func (builder *Builder) LightWhiteF() *Builder { - return builder.With(LightWhiteF) -} - -// LightBlackB is a syntax for LightBlackB. -func (builder *Builder) LightBlackB() *Builder { - return builder.With(LightBlackB) -} - -// LightRedB is a syntax for LightRedB. -func (builder *Builder) LightRedB() *Builder { - return builder.With(LightRedB) -} - -// LightGreenB is a syntax for LightGreenB. -func (builder *Builder) LightGreenB() *Builder { - return builder.With(LightGreenB) -} - -// LightYellowB is a syntax for LightYellowB. -func (builder *Builder) LightYellowB() *Builder { - return builder.With(LightYellowB) -} - -// LightBlueB is a syntax for LightBlueB. -func (builder *Builder) LightBlueB() *Builder { - return builder.With(LightBlueB) -} - -// LightMagentaB is a syntax for LightMagentaB. -func (builder *Builder) LightMagentaB() *Builder { - return builder.With(LightMagentaB) -} - -// LightCyanB is a syntax for LightCyanB. -func (builder *Builder) LightCyanB() *Builder { - return builder.With(LightCyanB) -} - -// LightWhiteB is a syntax for LightWhiteB. -func (builder *Builder) LightWhiteB() *Builder { - return builder.With(LightWhiteB) -} - -// Color3BitF is a syntax for Color3BitF. -func (builder *Builder) Color3BitF(c RGB3Bit) *Builder { - return builder.With(Color3BitF(c)) -} - -// Color3BitB is a syntax for Color3BitB. -func (builder *Builder) Color3BitB(c RGB3Bit) *Builder { - return builder.With(Color3BitB(c)) -} - -// Color8BitF is a syntax for Color8BitF. -func (builder *Builder) Color8BitF(c RGB8Bit) *Builder { - return builder.With(Color8BitF(c)) -} - -// Color8BitB is a syntax for Color8BitB. -func (builder *Builder) Color8BitB(c RGB8Bit) *Builder { - return builder.With(Color8BitB(c)) -} - -// FullColorF is a syntax for FullColorF. -func (builder *Builder) FullColorF(r, g, b uint8) *Builder { - return builder.With(FullColorF(r, g, b)) -} - -// FullColorB is a syntax for FullColorB. -func (builder *Builder) FullColorB(r, g, b uint8) *Builder { - return builder.With(FullColorB(r, g, b)) -} - -// RGB3BitF is a syntax for Color3BitF with NewRGB3Bit. -func (builder *Builder) RGB3BitF(r, g, b uint8) *Builder { - return builder.Color3BitF(NewRGB3Bit(r, g, b)) -} - -// RGB3BitB is a syntax for Color3BitB with NewRGB3Bit. -func (builder *Builder) RGB3BitB(r, g, b uint8) *Builder { - return builder.Color3BitB(NewRGB3Bit(r, g, b)) -} - -// RGB8BitF is a syntax for Color8BitF with NewRGB8Bit. -func (builder *Builder) RGB8BitF(r, g, b uint8) *Builder { - return builder.Color8BitF(NewRGB8Bit(r, g, b)) -} - -// RGB8BitB is a syntax for Color8BitB with NewRGB8Bit. -func (builder *Builder) RGB8BitB(r, g, b uint8) *Builder { - return builder.Color8BitB(NewRGB8Bit(r, g, b)) -} - -func init() { - EmptyBuilder = &Builder{empty} -} diff --git a/vendor/github.com/morikuni/aec/sample.gif b/vendor/github.com/morikuni/aec/sample.gif deleted file mode 100644 index c6c613bb70645efa4e184726060ea1ff981eeceb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12548 zcmeHtXHe7ox^?KiNed7{8X;7XCP*=%29P2G0wRPS6cCY(5D}@N_aaD@UX-rVRGLyn ziUk#vP5`li6zlsB?&3b@?0xn-bLW1#I^&ms!?1qqS><^Q4E0qHIxs9l8jiG4D5=G zkc%wJQx+903onrs@|6>>krR&H55KY>eoh`;asZm7fND|@8CDR!sE7_%MAs^cwkwL% zD8UkxCDWAAxhk0ZDx%L+gi8*hnhqkK92Ch^mCRSgl&MNwQ$;^kh1^y{4XcSwtBI7U zOIE2%HL9a~)WsLnMc33J&6<)AG*RQ4$Z0M3oEDOz1$(b0YH(Pw?XYC`VaYpKsV=P4 z7FJXVhd0D24dNsp;UpHd#UJTNZt5VXbS0+rBajp4Phz6_~W&Tz}DWZtdlR_FHdX zbw;p>nRc|ipYKnXb{y$w-B=ziF)lQ{-S%;9vg!1zk=yOtZ)bYq9mUM%UMfA9n94_HLw{y+a(h(q-H)YoF^N>j>XMNzW=%^r(B zo(sGdWe;Xm(&m&J4NpP=hLMdqme=}W3IoesvgnH&z-y5>+3elk1COcaV|B0R4H$9Y zV*2>z@q}O<@LD9v%r8`##56I&r^e>X2z1>hQ07gn4Oe)0x)57)f?6Z+T3DWpO+>(w z>MQt9F%RMD^U($GTVz$+w>n>xyGT1aY;RqzrjI&k+M=7B6Ttxi%Q#QpELdhJQ~WMw zrd9O}%uo?|yP&=kswoRaNCawq{q$jH<8$z(&I>QTF$-N~5~0(e?+vAYzwBrOT3w!r zIIv#MgcGuVLgREB?jH?3m{G>GkIoQ(H43Z^ycVgIdj(kkQGrfjQfKIB7>WB`iZeTV zDFP?^gs~(6!zhWus|6oSv9)GywvA@u-yUUr%Yidbb%azIq|wNzEo9j{_eP}B_#TW- zr16?9#`Q1WA7vD=qshlQS__p!U07Yq&z@YW^3YK)59q?W-}e|55j$k54LvS^H!pPh z>M0R?L0_s0XR*@INk(%=>L+B7Gm$#t_D_0q>8waq&>YTY$&~b)Z5}jE4d2Dfyh!xc zqvg6veBEv^D18mIao_Qpn%-4O0~-fstT}^Is@kX{Nw;&9USun7v>{JYox4d{U~N5X zYUTY3c1q1@)ZJD|mncx`v+Rjm43R#Q!eOs+67*;_)hVXq0E*zp`ncvfcK40?+b&LW zuF##nVk`4s{20GLStcc=Qo3nPM&-L9hw*yXoa~pPnrK@qnC`Jz-I{b}<=Z?^4?m~x z*QbxFck?DmxZQ}6BRz~$@PFN3$guW!E!ZHi<@ zMhcql2!%1dB+rs1iuusFx^h7aQ7BGTc)D4^zJY zH=l4Jr6WOWbx-BYUssFVYg@lLuciL>#^*bq(9Lv*+upVDp6OWY7rgQLL)JmFM;oI| za$n6K9sj=lQQNKV;;Sj9#jo2JqPZUJEG&C}Gow^o+Ww?<<88?FyKU6>FXx^-9Zx!hv)_14rhhu5DCU4NsxrVV%*@?Lx>=@Sb;o*5Cyd;CimDp(W!r0-= z{HeGa4(&)phc3(U{%(P`cTw^QPHYUg9^vQj$l)nhIoZN{pig|GvFxE-DHp-LqMQxU zdXHv#&SvWh$-O6=B+T-9gZ03s@1w2!XZby|^<;e-;uXIjz{gweL6RCG-87KG_bT-n z%Nr7XT#=B^+xOMRk0u59JBn^p8fbiYf8oLxBWTrb%qQ{ji!nMIg+vEJKl+S9s284(QkX=Nod_q1+A_ULu0)}7Y7rh6OE zx-99*MnLOiNdZ)?GrXBd)wr#t6AL46eeUF%4*DhZ9J z9~ShtozIU{i47IouQjo~A^$?v?%}sF^af>qXmi8i&ezMEv#(y6DIEU(9kI(a6DrCA zK8ngm0b0jmp*?evQJarN0?;~mRGJ3SF;X}H!xIf9Pjbf~vSPSn(dDY#acnf>{qgem zcbs8T7JbFq%nFq*;>xDyU9`zZ5DO`~tU>tX@vkxF*grJyFVR8(Xqo;4v=}id*gu?! zVFE*B?^uste|Y+D&LmRkb$wn>T3K}No-^5Wr^}}bLD4a;@ZvpZ@{urtW)PVfQ!K5f zI+HZ7nN9+arh6~dnaJuwWTpXUa$JU6(`yw#OArIr#D8Li9@!~j%VK8*oJrs;S<_y` zxS%7jM^w|A)f{jpKCv3vO#V<4J1-V3(iNiIgEr+y+?90g1tu?+B8M7Juf06^A+bQF zCWuWeX^eTOqBmVSdJ?1%8^NKwzfkL<;ls73{N}F;g4wp-K5vb`^Jixg|7yPPqFG_> zmz|IQ!I{K8Vnnj5^b-&)`pmrWTuY);R1UrpZs@H#HyfSol{QO8U0H~Z5ieIAk408f ziuGmgV37I;Mu_ve%KChU5*k|+WOBw-AR&ocuX`XBj}9tDX$#|B)6Ef^t{Ik`N^Y5! z4zc1Hc5?K1B!Mi6&JOe1b-c{FzB7L%GkZns3X71!K%V~-wPm=^7L$bb&&EdqfK=-r zK>CN-+|0f@2+<_n_Xq!GHuyb)Svx&Sj+U4ez-T|0R&Z60JLHY<@Y10#( z(aCa{W$u#z0iUwq?()?GX7gB^gho8{_OZBvyQRl!pq{#1sgLVj&d{H;1I#9CJORT@ z>qeaF467MEcE1NJcpmuCg*#fkAS!PouewZxZ>%*OjBH&YDQvy1=6&69eOB~mv&qmp zbeHAsx2L;1>;G;xKRo>%(jA`PA)VF#3DST)NGr#vkRtQ|NK149NL_S(h7|lKNNK5% zvI3Brm>Mo7T05w@WKqd`nLyrkgW0Y2m1(Pgt8^E4dw$-XO5Wu>|G^-9?#J7)|A@TW zASRF;&4K?iYWb`vV>+Ne$U8s|PzliZ73ntD#?+GGAF)C~*Cbbi8Y}#XqMF8*0@PS> zELrKyJM&Leq^&QKSmgOJPXO}1)F6dQTQvZq_G7kxbZ4#fQ-HjJSD%FWuB}c>Z)4~> zJa$>3Uz%mRIwE`+bQ7dfUQ~baFI^(6nE>UYoC@(yu*V- zs5xNN9t)Ojzv&&-d}i%s{)Jm-p54Cm=UDM}Wc1*nLI>qT{;NO7iqt*wE_j2h9P6~k zcDG?H-dD^ng`jtK_TN0)d-r>Z$@Zc|kwFMZbtX)J9}Ej;*DfVQa39(vMDn4PoODzD zi-A~i3U3(o;w1A?R9*&P6vd5bivtj~%+B$07R)XQ+#`5ogbJ09d*lt9qSz;~x=qfe zW->p6q*D2qZmz$(05?+TL;Z=5763}n|AtbW#U^p8CAI(FAK}kVwR$t~*YJmG)i;Z0 zP(3Gym;Vv|$iXGi5u?=bXL727GENPDwIS)?!;*(2XNbHzy-=WazjyZ(+ zMc2JwE=g2+rOL#(xmLJ;xbpo~&=xiPHT)Q{RaVu@F?YU>e|$InZ{aWeF(Z;*08c>B zpj81DDp3d#IT*~Wj<>4wY*ez>zS&5K{z5caluQ|o7KtMwv{40>#W=}YiZe)-I#`vS z5Rr))9Ylu&>R?UAGVYe34rTSZq{5-GsAwZONvCvEH1nc%sFL$yrj4BtK4ZqDYBb>> z*_P$g%6x10Qx19fF-0DSf%As0*&-R{U{i2$fra;)Q zB-Hi-F_jghV~+O!$o6a#lpLfsfll6m8MH^jBsKFxFdI>x42MxD<>|L?2G+CW>0GX=472}$wC?^CsDP76MjH4FauEC~M zCuJY7B7Ql|p2acCIRx*XBU%uN&i=CCv6 zYK$-mUo^}S_wyX~1Cag(`iIWeAX#lQ24a}@pzlYElLq5Xlm8g(x!2+x6tSNi*a&A& zmGz~zIK=x11QU3##W_SGsRAv|su4dz$Odq>(t5I_yg;DEk?Eoh-b|1my6J6IO3G-< zH$IQCtomhR^|q8n*UP)1YNliJ;y{bTw@rx+YiV$af`0@D9%=OhDLKiW*0-mjEIkZ$ zT*ZOf{9hi-F{$x+VQV(}xPG8pllxCCjY|siKb-9s_5P!sv`DE>ORb4 zqh<3w5KE|_7Hta6CCj?Fa`_A(e0(f7WMFtqSvgAeKKv$r7>t1#TRk;=fG37R!{A4R zZH#aEJZ>R1@;&JEkDk68nmi|8wQM*5595^%X^pIh?q?G)E_i*G0uiw~GSYwrW^FV9 z%FEpnwvyLc2za0D2uv5_k=SbmUt6!e3cvo5uk68v1BK;`IQw-IjdyP=8KTy@>^jt@ z8y#8sT%9dKH`Y9v*1GoD63jGjHN^LC8%>vH=b&>F9N+RAK>E&&G!{C3>`o98qx|lD z@VPGZ0+^XFKK{xgL*{=i+9nAi3H}tP=vX2i4$sXXI>+Y3s5*%xHB;u0xuul|a!9W# zGEwCv(J4`36%S9=vSuy?gw%N<6)$XPn9|GvkTGwMj7HrHUZxJage*Iiez(g^AuR5p z&I*8#63eU5SHcojY;)N7a~AS4Tb>E!u>wL`5WLm83=gm%d;CdA(*ST^{yn%ej7YaPB-oQ{i%6 z?(^}R-u;@XQ!hQuJ)^LB{w18&gqFmQm;4;nJhG+mEvO zV%KiLHzwM5^99_8>wSN3QD0T=eBN1GJ05fQ@W9u9ZBZM6z{0K1?1bQWV$hEUyT>@8 z`NyAIIpNa-3@}Ug_-CQ*;-sPv%u-zePgH8! z7raf1QFotf`WsD_#UKmQm6Mt5z%0$O4`_9RS&u|5YO8)Ax{EsvDwhMZbZ#lvw=D>N z1Bi=8@$Wn>qKjVOH;`ds0-fNaQ3Xf_?j-*fh0?vMoG&{p9*SVo z=^QIr9$|?gZ0a7c!QvqWB(e;?GQHwq4mFV4`D*i*s`9pBttcw`E7XDS>r-ZtMeY=I2XRW?uo!|+6$Y_-vjX??a+1lR>g{uJGTwin0v&C zN&Z^eNYW&GAT#PPZg=y&YvBcY0WeQ6V?MR=eD@e$>5X1fQ!M_3^wt%r63Nq?7#YTtC&V{MwJ?dT7+o6ija;!0|pOs$%dxN-md_@nXHh zg5w3qv6}&Q9m?Y#BdoLYxP0_>GDq{7yPIhCiF%sQwaa(zaawVoJuUYL8;F7&#B`+L zWHP#8`#Vl(Thmv##tTnoC=^d@jV79-bc5b5Q-yO`ynu)8FDV-_es z4>!gx$ghirX zqE6#O8oQX)`w?}ni<>QGW}53y9JwxRb<&RaZ_h-3zX*HY)2mtCL01Y@p~HN@1~WLsd0W zw_6NaIlBt8rUmlns4=t{A|o$Ayc+b5I9`T}2SoSrj6gYSo&I&8@iV>7(M1w9Rwwr{_QZQck(H&=D+e#q&4>oZ?@`?Eprcn#AViEqK5w%&fO-S2q# z%(rhJ8HK2tla=gcm4(?dmC6+?~fhi z0cUC*i;;n$k_ysw1pN1U*(BcTJoX&S>^wI;GSd`cedib|pI&ky1!vLi zVyyKE(9t6*E2#7|$bdzf#VG@~%!!k+Wqx)(lJ=Kn03FSC%~ErRIh>+jGQ#d#aToV= zZ+15TGRbm&;PW7S9{9n)(Vw{YmvD~*aM%6~+`q1z_q)#&N5^!tTP;z>6w7t)Q^QK6 z>ea#iB$jg>d9ki#04eut<*@L=g*6Qz^u&7Cg`_;7bx_7Iu_Z9rkq}?Zx%>NRjGIn9 zXw|FkN#(g2Cz{((V-OR(87V$=b6uy2`(y%Y=4S15gs-T3J>6!l|bz8u* zN9>6+Hy?-~yrKy1+fcdp=R*--)^PB^m6i?iT`P*@yi-xUI%$}2aYS?W3}pY?$op3} z#av`9GC&B)_a@Lw;L_z}k zoe)Bt0Or(KiiU4JAtPmO0+?gU`}4)*2UT4XRSp@rB&c!Ta!Ky}nhjvi=edxoXF*%4 zt33x`ZmusWo{=UabTr+%jqH|H;XP31;SeHen=J`oo71W2p92b|0?=R7ejJLvV>%00Sv5(_*k7*+BrLn|@2`p`2;-!IKho9cG7xeie*kHuz|OO=Gy;Si&MAby6VU&eOXVB!OHAajo_;w4zX5di zkUBZksyOIr0%4-s3S&JxLFe9Ho3DOLw!2cDzChXNR^9P-#sSW$wOj9Al`|G9fMuT6 z&zFR<%!%W78rj`u=23^ICG{!QcYXHpP{vE%0J} z8?{?+$?aTQ-%KD*z7aj~(vER~P9GKrlLdo0Z?}a0R{NdrtLcf)6{}lT5Bxys%l*?e z!InzGhqZ@={aQZSx%3!9XwJ^Iok$X}VL|5d5n*RTly+c|`%Eb(B0241M99KR_njTtPhefJN|+>WJU8 zviQK&tOU$KG61Cbkc1>}?bw8K*n?cQeJwzB?QH)@V2+3*5Q{l}VTO^iJV$l9+JA=db5wOxd;!kv4QS8HFDoo5Sg`B4$d zk#>dxJqY0(S+6lRu!i*e*~hiqW9Ey)hKtmF95A!aANe-%8{;N-!j!P?XwBI~d z$-)Faa<<``_lp`{f1DF{0#xyCdYy`CI_!vMZ#rF{cYWv4mg7ZJaG9^SUW4>+y42^< zm0a+n;n*t+LwA2Y3klKA0M0@TJYT&As-xAhSARMS**Pkbpo?*ej8&Zk!*g9Loya*h z{Wc;=kr*JJ0=bnKk`aiAld8?OjYGFhf)f;+^^sOU&pV%_v5JpPIHKALQBI4 z3i;22Rwo*${Q`fz?Ez>Rc{Np?r0xDblMDsv1FlbYx%_3mh4&p;u z*KH#;HdQ^1&%b^VVX+Bg=|m3atKt%#hz5VC?NTNs6^-pq(9ZS=atH=*9OKI3VzcSp zZ53$rAg8fdJei0f(5aUmuCWG_V2d)0^H*$5UJy=)Wf%({sp-S6zoPMBdOFctL{4E1 zeJbFin=CjF7s6D?PU+!a(O+NVk-vE39Vl>9VC2io{5RVO_<44|@Q#jCAMAl5u+f%_ zWBYA8!oK*NDbtslvwh|?GQ;n1G@##f)g?g>a6bu}F?`h9p6IBbZ+j@VA_=9H&T+BX zlLGMEUW`jZPD{VFND`1rk-3kENT-m^9b}3&r|t0+E#YSZX-4DsN^JlpFJ@R88OFw# zodO{K(f<)_UDI9N49jiY3v#TkoI>A2TZAg@ty_d*vJKt&-7f^_)XWSA*VgA(mkea)AWycwY#2v*f5OUJSUN>8Y~HHb1Rk*_GP$xDMW=rLjtX z%{JCqL|~@Gqxab@&Itv}>S)QSc9uoCJUjk6#|RRy-{X>*y4kQW9-tarte@{?0;<8; z9r=ZDk&oa?uN?)P5^2!y+nOyQs-VQsz@*ZGEBsN2F;gI~aKP)wOlE8EJwN++wlR_B z`C-4_b=?|l1e`A^%Q(_hv~BZ`yRN|(@&VLF5b+Mn;%)aZ(4PJJW%Yoqcu; z^rD@48c|v!5kJaqa(+hC-h96{1XJh_(QawL_Ap(bA7V5H%!Uj@TZ!~tIV zl0G(?Fp(=G4QyAg6T{RrSVbp`Rwkb~Ix=CUTL`aY67t zqYJA=)-TgC}e>hXU zhfQ(#9nGa5Cw3zq6VwyCA}9-b6R6>}!9Sna@!#m`k3l76Gshr#8VBNJYO`755J22a zP||7~h?gH(=u1>v?RQB&upWa*fkNH_TUU;iR#ar-!)TKKFi9@Yae%Vf2EU%}>z&CH)it%uW9T z=6K%-Ix=upDf6QT`q2X>#=>;=<(Ws#--~2;>6_Pd)GUhz;i4VvoQBkoJaH(5J0>Ez z0Im>${t;j#xX3g8)Iw0ZWbVi*^Ir==_zmfPzi^LaJ@KBLY|<;Y&gM1rnZ5yE8ta)o-#<<3w9mD;?+DF2 zES0URSfg`al4y|umsWkG;Q?p6@%qs_n%8h_zNgZj8A3~6M^T%>(K~yQrjPHz-Mg2@ zcE3u@gq~gT`2DOB3=G#F`q=_(SbpedrTOprc~$pU{bW80=w}Oef`WqXyytKFX?Xl# zfWXiC$-*$OfHT#yHP5i%)Gf3BNk8?o_Vjbf>ks{`_<6W$10ZVsD~JpN_>}sYZU98Y zUJ8xZ5kRriEYIch?$gm8CM?h8#S3ae{KNJwa;D0&sbHQhgkibFKf*BJxw#>b+71QB z(}Wp7E4-%&S=1*LKq&`R$sKb&;heeHSJ6sPCX&t=kao zSPyvys>#$=JS=jn+73mhY>&#u5u?)}p9I{hqPwtJz6|3*!h}R9IL^tZWyqhvSx5KS zj;B)ZVd60S;MAB4!)q+Gh>n=AgPjo=tb}Lv_mHr-ej3thtNgow_$dx!X79NxMRD-U~8KZm@LAKgE$Ll1{C#o(5BI7i+Vv2*c7*|S?05=O%_UI~9s<-^y0f%V4+@&lKGB*Zz!stBk& zdMQd#n9+E}6+hMmkK*{jXO!Gz2PQl+!}^qDSr}xs{8GT`il_LMZel;GH0zX9Rdi&W Y(?6j)4M_L*quqaULH)mVw5$IA0FB)@mjD0& diff --git a/vendor/github.com/morikuni/aec/sgr.go b/vendor/github.com/morikuni/aec/sgr.go deleted file mode 100644 index 0ba3464e6db..00000000000 --- a/vendor/github.com/morikuni/aec/sgr.go +++ /dev/null @@ -1,202 +0,0 @@ -package aec - -import ( - "fmt" -) - -// RGB3Bit is a 3bit RGB color. -type RGB3Bit uint8 - -// RGB8Bit is a 8bit RGB color. -type RGB8Bit uint8 - -func newSGR(n uint) ANSI { - return newAnsi(fmt.Sprintf(esc+"%dm", n)) -} - -// NewRGB3Bit create a RGB3Bit from given RGB. -func NewRGB3Bit(r, g, b uint8) RGB3Bit { - return RGB3Bit((r >> 7) | ((g >> 6) & 0x2) | ((b >> 5) & 0x4)) -} - -// NewRGB8Bit create a RGB8Bit from given RGB. -func NewRGB8Bit(r, g, b uint8) RGB8Bit { - return RGB8Bit(16 + 36*(r/43) + 6*(g/43) + b/43) -} - -// Color3BitF set the foreground color of text. -func Color3BitF(c RGB3Bit) ANSI { - return newAnsi(fmt.Sprintf(esc+"%dm", c+30)) -} - -// Color3BitB set the background color of text. -func Color3BitB(c RGB3Bit) ANSI { - return newAnsi(fmt.Sprintf(esc+"%dm", c+40)) -} - -// Color8BitF set the foreground color of text. -func Color8BitF(c RGB8Bit) ANSI { - return newAnsi(fmt.Sprintf(esc+"38;5;%dm", c)) -} - -// Color8BitB set the background color of text. -func Color8BitB(c RGB8Bit) ANSI { - return newAnsi(fmt.Sprintf(esc+"48;5;%dm", c)) -} - -// FullColorF set the foreground color of text. -func FullColorF(r, g, b uint8) ANSI { - return newAnsi(fmt.Sprintf(esc+"38;2;%d;%d;%dm", r, g, b)) -} - -// FullColorB set the foreground color of text. -func FullColorB(r, g, b uint8) ANSI { - return newAnsi(fmt.Sprintf(esc+"48;2;%d;%d;%dm", r, g, b)) -} - -// Style -var ( - // Bold set the text style to bold or increased intensity. - Bold ANSI - - // Faint set the text style to faint. - Faint ANSI - - // Italic set the text style to italic. - Italic ANSI - - // Underline set the text style to underline. - Underline ANSI - - // BlinkSlow set the text style to slow blink. - BlinkSlow ANSI - - // BlinkRapid set the text style to rapid blink. - BlinkRapid ANSI - - // Inverse swap the foreground color and background color. - Inverse ANSI - - // Conceal set the text style to conceal. - Conceal ANSI - - // CrossOut set the text style to crossed out. - CrossOut ANSI - - // Frame set the text style to framed. - Frame ANSI - - // Encircle set the text style to encircled. - Encircle ANSI - - // Overline set the text style to overlined. - Overline ANSI -) - -// Foreground color of text. -var ( - // DefaultF is the default color of foreground. - DefaultF ANSI - - // Normal color - BlackF ANSI - RedF ANSI - GreenF ANSI - YellowF ANSI - BlueF ANSI - MagentaF ANSI - CyanF ANSI - WhiteF ANSI - - // Light color - LightBlackF ANSI - LightRedF ANSI - LightGreenF ANSI - LightYellowF ANSI - LightBlueF ANSI - LightMagentaF ANSI - LightCyanF ANSI - LightWhiteF ANSI -) - -// Background color of text. -var ( - // DefaultB is the default color of background. - DefaultB ANSI - - // Normal color - BlackB ANSI - RedB ANSI - GreenB ANSI - YellowB ANSI - BlueB ANSI - MagentaB ANSI - CyanB ANSI - WhiteB ANSI - - // Light color - LightBlackB ANSI - LightRedB ANSI - LightGreenB ANSI - LightYellowB ANSI - LightBlueB ANSI - LightMagentaB ANSI - LightCyanB ANSI - LightWhiteB ANSI -) - -func init() { - Bold = newSGR(1) - Faint = newSGR(2) - Italic = newSGR(3) - Underline = newSGR(4) - BlinkSlow = newSGR(5) - BlinkRapid = newSGR(6) - Inverse = newSGR(7) - Conceal = newSGR(8) - CrossOut = newSGR(9) - - BlackF = newSGR(30) - RedF = newSGR(31) - GreenF = newSGR(32) - YellowF = newSGR(33) - BlueF = newSGR(34) - MagentaF = newSGR(35) - CyanF = newSGR(36) - WhiteF = newSGR(37) - - DefaultF = newSGR(39) - - BlackB = newSGR(40) - RedB = newSGR(41) - GreenB = newSGR(42) - YellowB = newSGR(43) - BlueB = newSGR(44) - MagentaB = newSGR(45) - CyanB = newSGR(46) - WhiteB = newSGR(47) - - DefaultB = newSGR(49) - - Frame = newSGR(51) - Encircle = newSGR(52) - Overline = newSGR(53) - - LightBlackF = newSGR(90) - LightRedF = newSGR(91) - LightGreenF = newSGR(92) - LightYellowF = newSGR(93) - LightBlueF = newSGR(94) - LightMagentaF = newSGR(95) - LightCyanF = newSGR(96) - LightWhiteF = newSGR(97) - - LightBlackB = newSGR(100) - LightRedB = newSGR(101) - LightGreenB = newSGR(102) - LightYellowB = newSGR(103) - LightBlueB = newSGR(104) - LightMagentaB = newSGR(105) - LightCyanB = newSGR(106) - LightWhiteB = newSGR(107) -} diff --git a/vendor/github.com/opencontainers/image-spec/LICENSE b/vendor/github.com/opencontainers/image-spec/LICENSE deleted file mode 100644 index 9fdc20fdb6a..00000000000 --- a/vendor/github.com/opencontainers/image-spec/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2016 The Linux Foundation. - - 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. diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go deleted file mode 100644 index 35d8108958f..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -const ( - // AnnotationCreated is the annotation key for the date and time on which the image was built (date-time string as defined by RFC 3339). - AnnotationCreated = "org.opencontainers.image.created" - - // AnnotationAuthors is the annotation key for the contact details of the people or organization responsible for the image (freeform string). - AnnotationAuthors = "org.opencontainers.image.authors" - - // AnnotationURL is the annotation key for the URL to find more information on the image. - AnnotationURL = "org.opencontainers.image.url" - - // AnnotationDocumentation is the annotation key for the URL to get documentation on the image. - AnnotationDocumentation = "org.opencontainers.image.documentation" - - // AnnotationSource is the annotation key for the URL to get source code for building the image. - AnnotationSource = "org.opencontainers.image.source" - - // AnnotationVersion is the annotation key for the version of the packaged software. - // The version MAY match a label or tag in the source code repository. - // The version MAY be Semantic versioning-compatible. - AnnotationVersion = "org.opencontainers.image.version" - - // AnnotationRevision is the annotation key for the source control revision identifier for the packaged software. - AnnotationRevision = "org.opencontainers.image.revision" - - // AnnotationVendor is the annotation key for the name of the distributing entity, organization or individual. - AnnotationVendor = "org.opencontainers.image.vendor" - - // AnnotationLicenses is the annotation key for the license(s) under which contained software is distributed as an SPDX License Expression. - AnnotationLicenses = "org.opencontainers.image.licenses" - - // AnnotationRefName is the annotation key for the name of the reference for a target. - // SHOULD only be considered valid when on descriptors on `index.json` within image layout. - AnnotationRefName = "org.opencontainers.image.ref.name" - - // AnnotationTitle is the annotation key for the human-readable title of the image. - AnnotationTitle = "org.opencontainers.image.title" - - // AnnotationDescription is the annotation key for the human-readable description of the software packaged in the image. - AnnotationDescription = "org.opencontainers.image.description" -) diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go deleted file mode 100644 index fe799bd698c..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -import ( - "time" - - digest "github.com/opencontainers/go-digest" -) - -// ImageConfig defines the execution parameters which should be used as a base when running a container using an image. -type ImageConfig struct { - // User defines the username or UID which the process in the container should run as. - User string `json:"User,omitempty"` - - // ExposedPorts a set of ports to expose from a container running this image. - ExposedPorts map[string]struct{} `json:"ExposedPorts,omitempty"` - - // Env is a list of environment variables to be used in a container. - Env []string `json:"Env,omitempty"` - - // Entrypoint defines a list of arguments to use as the command to execute when the container starts. - Entrypoint []string `json:"Entrypoint,omitempty"` - - // Cmd defines the default arguments to the entrypoint of the container. - Cmd []string `json:"Cmd,omitempty"` - - // Volumes is a set of directories describing where the process is likely write data specific to a container instance. - Volumes map[string]struct{} `json:"Volumes,omitempty"` - - // WorkingDir sets the current working directory of the entrypoint process in the container. - WorkingDir string `json:"WorkingDir,omitempty"` - - // Labels contains arbitrary metadata for the container. - Labels map[string]string `json:"Labels,omitempty"` - - // StopSignal contains the system call signal that will be sent to the container to exit. - StopSignal string `json:"StopSignal,omitempty"` -} - -// RootFS describes a layer content addresses -type RootFS struct { - // Type is the type of the rootfs. - Type string `json:"type"` - - // DiffIDs is an array of layer content hashes (DiffIDs), in order from bottom-most to top-most. - DiffIDs []digest.Digest `json:"diff_ids"` -} - -// History describes the history of a layer. -type History struct { - // Created is the combined date and time at which the layer was created, formatted as defined by RFC 3339, section 5.6. - Created *time.Time `json:"created,omitempty"` - - // CreatedBy is the command which created the layer. - CreatedBy string `json:"created_by,omitempty"` - - // Author is the author of the build point. - Author string `json:"author,omitempty"` - - // Comment is a custom message set when creating the layer. - Comment string `json:"comment,omitempty"` - - // EmptyLayer is used to mark if the history item created a filesystem diff. - EmptyLayer bool `json:"empty_layer,omitempty"` -} - -// Image is the JSON structure which describes some basic information about the image. -// This provides the `application/vnd.oci.image.config.v1+json` mediatype when marshalled to JSON. -type Image struct { - // Created is the combined date and time at which the image was created, formatted as defined by RFC 3339, section 5.6. - Created *time.Time `json:"created,omitempty"` - - // Author defines the name and/or email address of the person or entity which created and is responsible for maintaining the image. - Author string `json:"author,omitempty"` - - // Architecture is the CPU architecture which the binaries in this image are built to run on. - Architecture string `json:"architecture"` - - // OS is the name of the operating system which the image is built to run on. - OS string `json:"os"` - - // Config defines the execution parameters which should be used as a base when running a container using the image. - Config ImageConfig `json:"config,omitempty"` - - // RootFS references the layer content addresses used by the image. - RootFS RootFS `json:"rootfs"` - - // History describes the history of each layer. - History []History `json:"history,omitempty"` -} diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go deleted file mode 100644 index 6e442a0853f..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -import digest "github.com/opencontainers/go-digest" - -// Descriptor describes the disposition of targeted content. -// This structure provides `application/vnd.oci.descriptor.v1+json` mediatype -// when marshalled to JSON. -type Descriptor struct { - // MediaType is the media type of the object this schema refers to. - MediaType string `json:"mediaType,omitempty"` - - // Digest is the digest of the targeted content. - Digest digest.Digest `json:"digest"` - - // Size specifies the size in bytes of the blob. - Size int64 `json:"size"` - - // URLs specifies a list of URLs from which this object MAY be downloaded - URLs []string `json:"urls,omitempty"` - - // Annotations contains arbitrary metadata relating to the targeted content. - Annotations map[string]string `json:"annotations,omitempty"` - - // Platform describes the platform which the image in the manifest runs on. - // - // This should only be used when referring to a manifest. - Platform *Platform `json:"platform,omitempty"` -} - -// Platform describes the platform which the image in the manifest runs on. -type Platform struct { - // Architecture field specifies the CPU architecture, for example - // `amd64` or `ppc64`. - Architecture string `json:"architecture"` - - // OS specifies the operating system, for example `linux` or `windows`. - OS string `json:"os"` - - // OSVersion is an optional field specifying the operating system - // version, for example on Windows `10.0.14393.1066`. - OSVersion string `json:"os.version,omitempty"` - - // OSFeatures is an optional field specifying an array of strings, - // each listing a required OS feature (for example on Windows `win32k`). - OSFeatures []string `json:"os.features,omitempty"` - - // Variant is an optional field specifying a variant of the CPU, for - // example `v7` to specify ARMv7 when architecture is `arm`. - Variant string `json:"variant,omitempty"` -} diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go deleted file mode 100644 index 4e6c4b23623..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -import "github.com/opencontainers/image-spec/specs-go" - -// Index references manifests for various platforms. -// This structure provides `application/vnd.oci.image.index.v1+json` mediatype when marshalled to JSON. -type Index struct { - specs.Versioned - - // Manifests references platform specific manifests. - Manifests []Descriptor `json:"manifests"` - - // Annotations contains arbitrary metadata for the image index. - Annotations map[string]string `json:"annotations,omitempty"` -} diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go deleted file mode 100644 index fc79e9e0d14..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -const ( - // ImageLayoutFile is the file name of oci image layout file - ImageLayoutFile = "oci-layout" - // ImageLayoutVersion is the version of ImageLayout - ImageLayoutVersion = "1.0.0" -) - -// ImageLayout is the structure in the "oci-layout" file, found in the root -// of an OCI Image-layout directory. -type ImageLayout struct { - Version string `json:"imageLayoutVersion"` -} diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go deleted file mode 100644 index 7ff32c40ba3..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -import "github.com/opencontainers/image-spec/specs-go" - -// Manifest provides `application/vnd.oci.image.manifest.v1+json` mediatype structure when marshalled to JSON. -type Manifest struct { - specs.Versioned - - // Config references a configuration object for a container, by digest. - // The referenced configuration object is a JSON blob that the runtime uses to set up the container. - Config Descriptor `json:"config"` - - // Layers is an indexed list of layers referenced by the manifest. - Layers []Descriptor `json:"layers"` - - // Annotations contains arbitrary metadata for the image manifest. - Annotations map[string]string `json:"annotations,omitempty"` -} diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go deleted file mode 100644 index bad7bb97f47..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -const ( - // MediaTypeDescriptor specifies the media type for a content descriptor. - MediaTypeDescriptor = "application/vnd.oci.descriptor.v1+json" - - // MediaTypeLayoutHeader specifies the media type for the oci-layout. - MediaTypeLayoutHeader = "application/vnd.oci.layout.header.v1+json" - - // MediaTypeImageManifest specifies the media type for an image manifest. - MediaTypeImageManifest = "application/vnd.oci.image.manifest.v1+json" - - // MediaTypeImageIndex specifies the media type for an image index. - MediaTypeImageIndex = "application/vnd.oci.image.index.v1+json" - - // MediaTypeImageLayer is the media type used for layers referenced by the manifest. - MediaTypeImageLayer = "application/vnd.oci.image.layer.v1.tar" - - // MediaTypeImageLayerGzip is the media type used for gzipped layers - // referenced by the manifest. - MediaTypeImageLayerGzip = "application/vnd.oci.image.layer.v1.tar+gzip" - - // MediaTypeImageLayerNonDistributable is the media type for layers referenced by - // the manifest but with distribution restrictions. - MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar" - - // MediaTypeImageLayerNonDistributableGzip is the media type for - // gzipped layers referenced by the manifest but with distribution - // restrictions. - MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip" - - // MediaTypeImageConfig specifies the media type for the image configuration. - MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json" -) diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/version.go b/vendor/github.com/opencontainers/image-spec/specs-go/version.go deleted file mode 100644 index 5d493df2330..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/version.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package specs - -import "fmt" - -const ( - // VersionMajor is for an API incompatible changes - VersionMajor = 1 - // VersionMinor is for functionality in a backwards-compatible manner - VersionMinor = 0 - // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 1 - - // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "" -) - -// Version is the specification version that the package types support. -var Version = fmt.Sprintf("%d.%d.%d%s", VersionMajor, VersionMinor, VersionPatch, VersionDev) diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/versioned.go b/vendor/github.com/opencontainers/image-spec/specs-go/versioned.go deleted file mode 100644 index 58a1510f33e..00000000000 --- a/vendor/github.com/opencontainers/image-spec/specs-go/versioned.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package specs - -// Versioned provides a struct with the manifest schemaVersion and mediaType. -// Incoming content with unknown schema version can be decoded against this -// struct to check the version. -type Versioned struct { - // SchemaVersion is the image manifest schema that this image follows - SchemaVersion int `json:"schemaVersion"` -} diff --git a/vendor/golang.org/x/net/internal/socks/client.go b/vendor/golang.org/x/net/internal/socks/client.go deleted file mode 100644 index 3d6f516a595..00000000000 --- a/vendor/golang.org/x/net/internal/socks/client.go +++ /dev/null @@ -1,168 +0,0 @@ -// 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. - -package socks - -import ( - "context" - "errors" - "io" - "net" - "strconv" - "time" -) - -var ( - noDeadline = time.Time{} - aLongTimeAgo = time.Unix(1, 0) -) - -func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) { - host, port, err := splitHostPort(address) - if err != nil { - return nil, err - } - if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() { - c.SetDeadline(deadline) - defer c.SetDeadline(noDeadline) - } - if ctx != context.Background() { - errCh := make(chan error, 1) - done := make(chan struct{}) - defer func() { - close(done) - if ctxErr == nil { - ctxErr = <-errCh - } - }() - go func() { - select { - case <-ctx.Done(): - c.SetDeadline(aLongTimeAgo) - errCh <- ctx.Err() - case <-done: - errCh <- nil - } - }() - } - - b := make([]byte, 0, 6+len(host)) // the size here is just an estimate - b = append(b, Version5) - if len(d.AuthMethods) == 0 || d.Authenticate == nil { - b = append(b, 1, byte(AuthMethodNotRequired)) - } else { - ams := d.AuthMethods - if len(ams) > 255 { - return nil, errors.New("too many authentication methods") - } - b = append(b, byte(len(ams))) - for _, am := range ams { - b = append(b, byte(am)) - } - } - if _, ctxErr = c.Write(b); ctxErr != nil { - return - } - - if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil { - return - } - if b[0] != Version5 { - return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) - } - am := AuthMethod(b[1]) - if am == AuthMethodNoAcceptableMethods { - return nil, errors.New("no acceptable authentication methods") - } - if d.Authenticate != nil { - if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil { - return - } - } - - b = b[:0] - b = append(b, Version5, byte(d.cmd), 0) - if ip := net.ParseIP(host); ip != nil { - if ip4 := ip.To4(); ip4 != nil { - b = append(b, AddrTypeIPv4) - b = append(b, ip4...) - } else if ip6 := ip.To16(); ip6 != nil { - b = append(b, AddrTypeIPv6) - b = append(b, ip6...) - } else { - return nil, errors.New("unknown address type") - } - } else { - if len(host) > 255 { - return nil, errors.New("FQDN too long") - } - b = append(b, AddrTypeFQDN) - b = append(b, byte(len(host))) - b = append(b, host...) - } - b = append(b, byte(port>>8), byte(port)) - if _, ctxErr = c.Write(b); ctxErr != nil { - return - } - - if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil { - return - } - if b[0] != Version5 { - return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) - } - if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded { - return nil, errors.New("unknown error " + cmdErr.String()) - } - if b[2] != 0 { - return nil, errors.New("non-zero reserved field") - } - l := 2 - var a Addr - switch b[3] { - case AddrTypeIPv4: - l += net.IPv4len - a.IP = make(net.IP, net.IPv4len) - case AddrTypeIPv6: - l += net.IPv6len - a.IP = make(net.IP, net.IPv6len) - case AddrTypeFQDN: - if _, err := io.ReadFull(c, b[:1]); err != nil { - return nil, err - } - l += int(b[0]) - default: - return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3]))) - } - if cap(b) < l { - b = make([]byte, l) - } else { - b = b[:l] - } - if _, ctxErr = io.ReadFull(c, b); ctxErr != nil { - return - } - if a.IP != nil { - copy(a.IP, b) - } else { - a.Name = string(b[:len(b)-2]) - } - a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1]) - return &a, nil -} - -func splitHostPort(address string) (string, int, error) { - host, port, err := net.SplitHostPort(address) - if err != nil { - return "", 0, err - } - portnum, err := strconv.Atoi(port) - if err != nil { - return "", 0, err - } - if 1 > portnum || portnum > 0xffff { - return "", 0, errors.New("port number out of range " + port) - } - return host, portnum, nil -} diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go deleted file mode 100644 index 97db2340ec9..00000000000 --- a/vendor/golang.org/x/net/internal/socks/socks.go +++ /dev/null @@ -1,317 +0,0 @@ -// 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. - -// Package socks provides a SOCKS version 5 client implementation. -// -// SOCKS protocol version 5 is defined in RFC 1928. -// Username/Password authentication for SOCKS version 5 is defined in -// RFC 1929. -package socks - -import ( - "context" - "errors" - "io" - "net" - "strconv" -) - -// A Command represents a SOCKS command. -type Command int - -func (cmd Command) String() string { - switch cmd { - case CmdConnect: - return "socks connect" - case cmdBind: - return "socks bind" - default: - return "socks " + strconv.Itoa(int(cmd)) - } -} - -// An AuthMethod represents a SOCKS authentication method. -type AuthMethod int - -// A Reply represents a SOCKS command reply code. -type Reply int - -func (code Reply) String() string { - switch code { - case StatusSucceeded: - return "succeeded" - case 0x01: - return "general SOCKS server failure" - case 0x02: - return "connection not allowed by ruleset" - case 0x03: - return "network unreachable" - case 0x04: - return "host unreachable" - case 0x05: - return "connection refused" - case 0x06: - return "TTL expired" - case 0x07: - return "command not supported" - case 0x08: - return "address type not supported" - default: - return "unknown code: " + strconv.Itoa(int(code)) - } -} - -// Wire protocol constants. -const ( - Version5 = 0x05 - - AddrTypeIPv4 = 0x01 - AddrTypeFQDN = 0x03 - AddrTypeIPv6 = 0x04 - - CmdConnect Command = 0x01 // establishes an active-open forward proxy connection - cmdBind Command = 0x02 // establishes a passive-open forward proxy connection - - AuthMethodNotRequired AuthMethod = 0x00 // no authentication required - AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password - AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authentication methods - - StatusSucceeded Reply = 0x00 -) - -// An Addr represents a SOCKS-specific address. -// Either Name or IP is used exclusively. -type Addr struct { - Name string // fully-qualified domain name - IP net.IP - Port int -} - -func (a *Addr) Network() string { return "socks" } - -func (a *Addr) String() string { - if a == nil { - return "" - } - port := strconv.Itoa(a.Port) - if a.IP == nil { - return net.JoinHostPort(a.Name, port) - } - return net.JoinHostPort(a.IP.String(), port) -} - -// A Conn represents a forward proxy connection. -type Conn struct { - net.Conn - - boundAddr net.Addr -} - -// BoundAddr returns the address assigned by the proxy server for -// connecting to the command target address from the proxy server. -func (c *Conn) BoundAddr() net.Addr { - if c == nil { - return nil - } - return c.boundAddr -} - -// A Dialer holds SOCKS-specific options. -type Dialer struct { - cmd Command // either CmdConnect or cmdBind - proxyNetwork string // network between a proxy server and a client - proxyAddress string // proxy server address - - // ProxyDial specifies the optional dial function for - // establishing the transport connection. - ProxyDial func(context.Context, string, string) (net.Conn, error) - - // AuthMethods specifies the list of request authentication - // methods. - // If empty, SOCKS client requests only AuthMethodNotRequired. - AuthMethods []AuthMethod - - // Authenticate specifies the optional authentication - // function. It must be non-nil when AuthMethods is not empty. - // It must return an error when the authentication is failed. - Authenticate func(context.Context, io.ReadWriter, AuthMethod) error -} - -// DialContext connects to the provided address on the provided -// network. -// -// The returned error value may be a net.OpError. When the Op field of -// net.OpError contains "socks", the Source field contains a proxy -// server address and the Addr field contains a command target -// address. -// -// See func Dial of the net package of standard library for a -// description of the network and address parameters. -func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { - if err := d.validateTarget(network, address); err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - if ctx == nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")} - } - var err error - var c net.Conn - if d.ProxyDial != nil { - c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress) - } else { - var dd net.Dialer - c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress) - } - if err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - a, err := d.connect(ctx, c, address) - if err != nil { - c.Close() - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - return &Conn{Conn: c, boundAddr: a}, nil -} - -// DialWithConn initiates a connection from SOCKS server to the target -// network and address using the connection c that is already -// connected to the SOCKS server. -// -// It returns the connection's local address assigned by the SOCKS -// server. -func (d *Dialer) DialWithConn(ctx context.Context, c net.Conn, network, address string) (net.Addr, error) { - if err := d.validateTarget(network, address); err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - if ctx == nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")} - } - a, err := d.connect(ctx, c, address) - if err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - return a, nil -} - -// Dial connects to the provided address on the provided network. -// -// Unlike DialContext, it returns a raw transport connection instead -// of a forward proxy connection. -// -// Deprecated: Use DialContext or DialWithConn instead. -func (d *Dialer) Dial(network, address string) (net.Conn, error) { - if err := d.validateTarget(network, address); err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - var err error - var c net.Conn - if d.ProxyDial != nil { - c, err = d.ProxyDial(context.Background(), d.proxyNetwork, d.proxyAddress) - } else { - c, err = net.Dial(d.proxyNetwork, d.proxyAddress) - } - if err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - if _, err := d.DialWithConn(context.Background(), c, network, address); err != nil { - c.Close() - return nil, err - } - return c, nil -} - -func (d *Dialer) validateTarget(network, address string) error { - switch network { - case "tcp", "tcp6", "tcp4": - default: - return errors.New("network not implemented") - } - switch d.cmd { - case CmdConnect, cmdBind: - default: - return errors.New("command not implemented") - } - return nil -} - -func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) { - for i, s := range []string{d.proxyAddress, address} { - host, port, err := splitHostPort(s) - if err != nil { - return nil, nil, err - } - a := &Addr{Port: port} - a.IP = net.ParseIP(host) - if a.IP == nil { - a.Name = host - } - if i == 0 { - proxy = a - } else { - dst = a - } - } - return -} - -// NewDialer returns a new Dialer that dials through the provided -// proxy server's network and address. -func NewDialer(network, address string) *Dialer { - return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect} -} - -const ( - authUsernamePasswordVersion = 0x01 - authStatusSucceeded = 0x00 -) - -// UsernamePassword are the credentials for the username/password -// authentication method. -type UsernamePassword struct { - Username string - Password string -} - -// Authenticate authenticates a pair of username and password with the -// proxy server. -func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error { - switch auth { - case AuthMethodNotRequired: - return nil - case AuthMethodUsernamePassword: - if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 { - return errors.New("invalid username/password") - } - b := []byte{authUsernamePasswordVersion} - b = append(b, byte(len(up.Username))) - b = append(b, up.Username...) - b = append(b, byte(len(up.Password))) - b = append(b, up.Password...) - // TODO(mikio): handle IO deadlines and cancelation if - // necessary - if _, err := rw.Write(b); err != nil { - return err - } - if _, err := io.ReadFull(rw, b[:2]); err != nil { - return err - } - if b[0] != authUsernamePasswordVersion { - return errors.New("invalid username/password version") - } - if b[1] != authStatusSucceeded { - return errors.New("username/password authentication failed") - } - return nil - } - return errors.New("unsupported authentication method " + strconv.Itoa(int(auth))) -} diff --git a/vendor/golang.org/x/net/proxy/dial.go b/vendor/golang.org/x/net/proxy/dial.go deleted file mode 100644 index 811c2e4e962..00000000000 --- a/vendor/golang.org/x/net/proxy/dial.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 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. - -package proxy - -import ( - "context" - "net" -) - -// A ContextDialer dials using a context. -type ContextDialer interface { - DialContext(ctx context.Context, network, address string) (net.Conn, error) -} - -// Dial works like DialContext on net.Dialer but using a dialer returned by FromEnvironment. -// -// The passed ctx is only used for returning the Conn, not the lifetime of the Conn. -// -// Custom dialers (registered via RegisterDialerType) that do not implement ContextDialer -// can leak a goroutine for as long as it takes the underlying Dialer implementation to timeout. -// -// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. -func Dial(ctx context.Context, network, address string) (net.Conn, error) { - d := FromEnvironment() - if xd, ok := d.(ContextDialer); ok { - return xd.DialContext(ctx, network, address) - } - return dialContext(ctx, d, network, address) -} - -// WARNING: this can leak a goroutine for as long as the underlying Dialer implementation takes to timeout -// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. -func dialContext(ctx context.Context, d Dialer, network, address string) (net.Conn, error) { - var ( - conn net.Conn - done = make(chan struct{}, 1) - err error - ) - go func() { - conn, err = d.Dial(network, address) - close(done) - if conn != nil && ctx.Err() != nil { - conn.Close() - } - }() - select { - case <-ctx.Done(): - err = ctx.Err() - case <-done: - } - return conn, err -} diff --git a/vendor/golang.org/x/net/proxy/direct.go b/vendor/golang.org/x/net/proxy/direct.go deleted file mode 100644 index 3d66bdef9d7..00000000000 --- a/vendor/golang.org/x/net/proxy/direct.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2011 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. - -package proxy - -import ( - "context" - "net" -) - -type direct struct{} - -// Direct implements Dialer by making network connections directly using net.Dial or net.DialContext. -var Direct = direct{} - -var ( - _ Dialer = Direct - _ ContextDialer = Direct -) - -// Dial directly invokes net.Dial with the supplied parameters. -func (direct) Dial(network, addr string) (net.Conn, error) { - return net.Dial(network, addr) -} - -// DialContext instantiates a net.Dialer and invokes its DialContext receiver with the supplied parameters. -func (direct) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { - var d net.Dialer - return d.DialContext(ctx, network, addr) -} diff --git a/vendor/golang.org/x/net/proxy/per_host.go b/vendor/golang.org/x/net/proxy/per_host.go deleted file mode 100644 index 573fe79e86e..00000000000 --- a/vendor/golang.org/x/net/proxy/per_host.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2011 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. - -package proxy - -import ( - "context" - "net" - "strings" -) - -// A PerHost directs connections to a default Dialer unless the host name -// requested matches one of a number of exceptions. -type PerHost struct { - def, bypass Dialer - - bypassNetworks []*net.IPNet - bypassIPs []net.IP - bypassZones []string - bypassHosts []string -} - -// NewPerHost returns a PerHost Dialer that directs connections to either -// defaultDialer or bypass, depending on whether the connection matches one of -// the configured rules. -func NewPerHost(defaultDialer, bypass Dialer) *PerHost { - return &PerHost{ - def: defaultDialer, - bypass: bypass, - } -} - -// Dial connects to the address addr on the given network through either -// defaultDialer or bypass. -func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) { - host, _, err := net.SplitHostPort(addr) - if err != nil { - return nil, err - } - - return p.dialerForRequest(host).Dial(network, addr) -} - -// DialContext connects to the address addr on the given network through either -// defaultDialer or bypass. -func (p *PerHost) DialContext(ctx context.Context, network, addr string) (c net.Conn, err error) { - host, _, err := net.SplitHostPort(addr) - if err != nil { - return nil, err - } - d := p.dialerForRequest(host) - if x, ok := d.(ContextDialer); ok { - return x.DialContext(ctx, network, addr) - } - return dialContext(ctx, d, network, addr) -} - -func (p *PerHost) dialerForRequest(host string) Dialer { - if ip := net.ParseIP(host); ip != nil { - for _, net := range p.bypassNetworks { - if net.Contains(ip) { - return p.bypass - } - } - for _, bypassIP := range p.bypassIPs { - if bypassIP.Equal(ip) { - return p.bypass - } - } - return p.def - } - - for _, zone := range p.bypassZones { - if strings.HasSuffix(host, zone) { - return p.bypass - } - if host == zone[1:] { - // For a zone ".example.com", we match "example.com" - // too. - return p.bypass - } - } - for _, bypassHost := range p.bypassHosts { - if bypassHost == host { - return p.bypass - } - } - return p.def -} - -// AddFromString parses a string that contains comma-separated values -// specifying hosts that should use the bypass proxy. Each value is either an -// IP address, a CIDR range, a zone (*.example.com) or a host name -// (localhost). A best effort is made to parse the string and errors are -// ignored. -func (p *PerHost) AddFromString(s string) { - hosts := strings.Split(s, ",") - for _, host := range hosts { - host = strings.TrimSpace(host) - if len(host) == 0 { - continue - } - if strings.Contains(host, "/") { - // We assume that it's a CIDR address like 127.0.0.0/8 - if _, net, err := net.ParseCIDR(host); err == nil { - p.AddNetwork(net) - } - continue - } - if ip := net.ParseIP(host); ip != nil { - p.AddIP(ip) - continue - } - if strings.HasPrefix(host, "*.") { - p.AddZone(host[1:]) - continue - } - p.AddHost(host) - } -} - -// AddIP specifies an IP address that will use the bypass proxy. Note that -// this will only take effect if a literal IP address is dialed. A connection -// to a named host will never match an IP. -func (p *PerHost) AddIP(ip net.IP) { - p.bypassIPs = append(p.bypassIPs, ip) -} - -// AddNetwork specifies an IP range that will use the bypass proxy. Note that -// this will only take effect if a literal IP address is dialed. A connection -// to a named host will never match. -func (p *PerHost) AddNetwork(net *net.IPNet) { - p.bypassNetworks = append(p.bypassNetworks, net) -} - -// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of -// "example.com" matches "example.com" and all of its subdomains. -func (p *PerHost) AddZone(zone string) { - if strings.HasSuffix(zone, ".") { - zone = zone[:len(zone)-1] - } - if !strings.HasPrefix(zone, ".") { - zone = "." + zone - } - p.bypassZones = append(p.bypassZones, zone) -} - -// AddHost specifies a host name that will use the bypass proxy. -func (p *PerHost) AddHost(host string) { - if strings.HasSuffix(host, ".") { - host = host[:len(host)-1] - } - p.bypassHosts = append(p.bypassHosts, host) -} diff --git a/vendor/golang.org/x/net/proxy/proxy.go b/vendor/golang.org/x/net/proxy/proxy.go deleted file mode 100644 index 9ff4b9a7767..00000000000 --- a/vendor/golang.org/x/net/proxy/proxy.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2011 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. - -// Package proxy provides support for a variety of protocols to proxy network -// data. -package proxy // import "golang.org/x/net/proxy" - -import ( - "errors" - "net" - "net/url" - "os" - "sync" -) - -// A Dialer is a means to establish a connection. -// Custom dialers should also implement ContextDialer. -type Dialer interface { - // Dial connects to the given address via the proxy. - Dial(network, addr string) (c net.Conn, err error) -} - -// Auth contains authentication parameters that specific Dialers may require. -type Auth struct { - User, Password string -} - -// FromEnvironment returns the dialer specified by the proxy-related -// variables in the environment and makes underlying connections -// directly. -func FromEnvironment() Dialer { - return FromEnvironmentUsing(Direct) -} - -// FromEnvironmentUsing returns the dialer specify by the proxy-related -// variables in the environment and makes underlying connections -// using the provided forwarding Dialer (for instance, a *net.Dialer -// with desired configuration). -func FromEnvironmentUsing(forward Dialer) Dialer { - allProxy := allProxyEnv.Get() - if len(allProxy) == 0 { - return forward - } - - proxyURL, err := url.Parse(allProxy) - if err != nil { - return forward - } - proxy, err := FromURL(proxyURL, forward) - if err != nil { - return forward - } - - noProxy := noProxyEnv.Get() - if len(noProxy) == 0 { - return proxy - } - - perHost := NewPerHost(proxy, forward) - perHost.AddFromString(noProxy) - return perHost -} - -// proxySchemes is a map from URL schemes to a function that creates a Dialer -// from a URL with such a scheme. -var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error) - -// RegisterDialerType takes a URL scheme and a function to generate Dialers from -// a URL with that scheme and a forwarding Dialer. Registered schemes are used -// by FromURL. -func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) { - if proxySchemes == nil { - proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error)) - } - proxySchemes[scheme] = f -} - -// FromURL returns a Dialer given a URL specification and an underlying -// Dialer for it to make network requests. -func FromURL(u *url.URL, forward Dialer) (Dialer, error) { - var auth *Auth - if u.User != nil { - auth = new(Auth) - auth.User = u.User.Username() - if p, ok := u.User.Password(); ok { - auth.Password = p - } - } - - switch u.Scheme { - case "socks5", "socks5h": - addr := u.Hostname() - port := u.Port() - if port == "" { - port = "1080" - } - return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward) - } - - // If the scheme doesn't match any of the built-in schemes, see if it - // was registered by another package. - if proxySchemes != nil { - if f, ok := proxySchemes[u.Scheme]; ok { - return f(u, forward) - } - } - - return nil, errors.New("proxy: unknown scheme: " + u.Scheme) -} - -var ( - allProxyEnv = &envOnce{ - names: []string{"ALL_PROXY", "all_proxy"}, - } - noProxyEnv = &envOnce{ - names: []string{"NO_PROXY", "no_proxy"}, - } -) - -// envOnce looks up an environment variable (optionally by multiple -// names) once. It mitigates expensive lookups on some platforms -// (e.g. Windows). -// (Borrowed from net/http/transport.go) -type envOnce struct { - names []string - once sync.Once - val string -} - -func (e *envOnce) Get() string { - e.once.Do(e.init) - return e.val -} - -func (e *envOnce) init() { - for _, n := range e.names { - e.val = os.Getenv(n) - if e.val != "" { - return - } - } -} - -// reset is used by tests -func (e *envOnce) reset() { - e.once = sync.Once{} - e.val = "" -} diff --git a/vendor/golang.org/x/net/proxy/socks5.go b/vendor/golang.org/x/net/proxy/socks5.go deleted file mode 100644 index c91651f96db..00000000000 --- a/vendor/golang.org/x/net/proxy/socks5.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2011 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. - -package proxy - -import ( - "context" - "net" - - "golang.org/x/net/internal/socks" -) - -// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given -// address with an optional username and password. -// See RFC 1928 and RFC 1929. -func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) { - d := socks.NewDialer(network, address) - if forward != nil { - if f, ok := forward.(ContextDialer); ok { - d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) { - return f.DialContext(ctx, network, address) - } - } else { - d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) { - return dialContext(ctx, forward, network, address) - } - } - } - if auth != nil { - up := socks.UsernamePassword{ - Username: auth.User, - Password: auth.Password, - } - d.AuthMethods = []socks.AuthMethod{ - socks.AuthMethodNotRequired, - socks.AuthMethodUsernamePassword, - } - d.Authenticate = up.Authenticate - } - return d, nil -} diff --git a/vendor/k8s.io/utils/net/ebtables/ebtables.go b/vendor/k8s.io/utils/net/ebtables/ebtables.go deleted file mode 100644 index 3e984a27ee4..00000000000 --- a/vendor/k8s.io/utils/net/ebtables/ebtables.go +++ /dev/null @@ -1,222 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package ebtables allows to control the ebtables Linux-based bridging firewall. -// Both chains and rules can be added, deleted and modified. -// For ebtables specific documentation see: http://ebtables.netfilter.org/ -package ebtables - -import ( - "fmt" - "regexp" - "strings" - - utilexec "k8s.io/utils/exec" -) - -const ( - cmdebtables = "ebtables" - - // Flag to show full mac in output. The default representation omits leading zeroes. - fullMac = "--Lmac2" -) - -// RulePosition is the rule position within a table -type RulePosition string - -// Relative position for a new rule -const ( - Prepend RulePosition = "-I" - Append RulePosition = "-A" -) - -// Table is an Ebtables table type -type Table string - -// Tables available in ebtables by default -const ( - TableNAT Table = "nat" - TableFilter Table = "filter" - TableBroute Table = "broute" -) - -// Chain is an Ebtables chain type -type Chain string - -// Chains that are built-in in ebtables -const ( - ChainPostrouting Chain = "POSTROUTING" - ChainPrerouting Chain = "PREROUTING" - ChainOutput Chain = "OUTPUT" - ChainInput Chain = "INPUT" - ChainBrouting Chain = "BROUTING" -) - -type operation string - -const ( - opCreateChain operation = "-N" - opFlushChain operation = "-F" - opDeleteChain operation = "-X" - opListChain operation = "-L" - opAppendRule operation = "-A" - opPrependRule operation = "-I" - opDeleteRule operation = "-D" -) - -// Interface for running ebtables commands. Implementations must be goroutine-safe. -type Interface interface { - // GetVersion returns the "X.Y.Z" semver string for ebtables. - GetVersion() (string, error) - // EnsureRule checks if the specified rule is present and, if not, creates it. If the rule existed, return true. - // WARNING: ebtables does not provide check operation like iptables do. Hence we have to do a string match of args. - // Input args must follow the format and sequence of ebtables list output. Otherwise, EnsureRule will always create - // new rules and causing duplicates. - EnsureRule(position RulePosition, table Table, chain Chain, args ...string) (bool, error) - // DeleteRule checks if the specified rule is present and, if so, deletes it. - DeleteRule(table Table, chain Chain, args ...string) error - // EnsureChain checks if the specified chain is present and, if not, creates it. If the rule existed, return true. - EnsureChain(table Table, chain Chain) (bool, error) - // DeleteChain deletes the specified chain. If the chain did not exist, return error. - DeleteChain(table Table, chain Chain) error - // FlushChain flush the specified chain. If the chain did not exist, return error. - FlushChain(table Table, chain Chain) error -} - -// runner implements Interface in terms of exec("ebtables"). -type runner struct { - exec utilexec.Interface -} - -// New returns a new Interface which will exec ebtables. -func New(exec utilexec.Interface) Interface { - runner := &runner{ - exec: exec, - } - return runner -} - -func makeFullArgs(table Table, op operation, chain Chain, args ...string) []string { - return append([]string{"-t", string(table), string(op), string(chain)}, args...) -} - -// getEbtablesVersionString runs "ebtables --version" to get the version string -// in the form "X.X.X" -func getEbtablesVersionString(exec utilexec.Interface) (string, error) { - // this doesn't access mutable state so we don't need to use the interface / runner - bytes, err := exec.Command(cmdebtables, "--version").CombinedOutput() - if err != nil { - return "", err - } - versionMatcher := regexp.MustCompile(`v([0-9]+\.[0-9]+\.[0-9]+)`) - match := versionMatcher.FindStringSubmatch(string(bytes)) - if match == nil { - return "", fmt.Errorf("no ebtables version found in string: %s", bytes) - } - return match[1], nil -} - -func (runner *runner) GetVersion() (string, error) { - return getEbtablesVersionString(runner.exec) -} - -func (runner *runner) EnsureRule(position RulePosition, table Table, chain Chain, args ...string) (bool, error) { - var exist bool - fullArgs := makeFullArgs(table, opListChain, chain, fullMac) - out, err := runner.exec.Command(cmdebtables, fullArgs...).CombinedOutput() - if err != nil { - exist = false - } else { - exist = checkIfRuleExists(string(out), args...) - } - if !exist { - fullArgs = makeFullArgs(table, operation(position), chain, args...) - out, err := runner.exec.Command(cmdebtables, fullArgs...).CombinedOutput() - if err != nil { - return exist, fmt.Errorf("Failed to ensure rule: %v, output: %v", err, string(out)) - } - } - return exist, nil -} - -func (runner *runner) DeleteRule(table Table, chain Chain, args ...string) error { - var exist bool - fullArgs := makeFullArgs(table, opListChain, chain, fullMac) - out, err := runner.exec.Command(cmdebtables, fullArgs...).CombinedOutput() - if err != nil { - exist = false - } else { - exist = checkIfRuleExists(string(out), args...) - } - - if !exist { - return nil - } - fullArgs = makeFullArgs(table, opDeleteRule, chain, args...) - out, err = runner.exec.Command(cmdebtables, fullArgs...).CombinedOutput() - if err != nil { - return fmt.Errorf("Failed to delete rule: %v, output: %s", err, out) - } - return nil -} - -func (runner *runner) EnsureChain(table Table, chain Chain) (bool, error) { - exist := true - - args := makeFullArgs(table, opListChain, chain) - _, err := runner.exec.Command(cmdebtables, args...).CombinedOutput() - if err != nil { - exist = false - } - if !exist { - args = makeFullArgs(table, opCreateChain, chain) - out, err := runner.exec.Command(cmdebtables, args...).CombinedOutput() - if err != nil { - return exist, fmt.Errorf("Failed to ensure %v chain: %v, output: %v", chain, err, string(out)) - } - } - return exist, nil -} - -// checkIfRuleExists takes the output of ebtables list chain and checks if the input rules exists -// WARNING: checkIfRuleExists expects the input args matches the format and sequence of ebtables list output -func checkIfRuleExists(listChainOutput string, args ...string) bool { - rule := strings.Join(args, " ") - for _, line := range strings.Split(listChainOutput, "\n") { - if strings.TrimSpace(line) == rule { - return true - } - } - return false -} - -func (runner *runner) DeleteChain(table Table, chain Chain) error { - fullArgs := makeFullArgs(table, opDeleteChain, chain) - out, err := runner.exec.Command(cmdebtables, fullArgs...).CombinedOutput() - if err != nil { - return fmt.Errorf("Failed to delete %v chain %v: %v, output: %v", string(table), string(chain), err, string(out)) - } - return nil -} - -func (runner *runner) FlushChain(table Table, chain Chain) error { - fullArgs := makeFullArgs(table, opFlushChain, chain) - out, err := runner.exec.Command(cmdebtables, fullArgs...).CombinedOutput() - if err != nil { - return fmt.Errorf("Failed to flush %v chain %v: %v, output: %v", string(table), string(chain), err, string(out)) - } - return nil -} diff --git a/vendor/modules.txt b/vendor/modules.txt index f4ec6ed3e58..922b90870cd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -187,20 +187,8 @@ github.com/containerd/containerd/api/services/tasks/v1 github.com/containerd/containerd/api/services/version/v1 github.com/containerd/containerd/api/types github.com/containerd/containerd/api/types/task -github.com/containerd/containerd/errdefs -github.com/containerd/containerd/log -github.com/containerd/containerd/platforms # github.com/containerd/ttrpc v1.0.2 => github.com/containerd/ttrpc v1.0.2 github.com/containerd/ttrpc -# github.com/containernetworking/cni v0.8.1 => github.com/containernetworking/cni v0.8.1 -## explicit -github.com/containernetworking/cni/libcni -github.com/containernetworking/cni/pkg/invoke -github.com/containernetworking/cni/pkg/types -github.com/containernetworking/cni/pkg/types/020 -github.com/containernetworking/cni/pkg/types/current -github.com/containernetworking/cni/pkg/utils -github.com/containernetworking/cni/pkg/version # github.com/coredns/caddy v1.1.0 => github.com/coredns/caddy v1.1.0 github.com/coredns/caddy/caddyfile # github.com/coredns/corefile-migration v1.0.14 => github.com/coredns/corefile-migration v1.0.14 @@ -233,34 +221,6 @@ github.com/daviddengcn/go-colortext ## explicit github.com/docker/distribution/digestset github.com/docker/distribution/reference -github.com/docker/distribution/registry/api/errcode -# github.com/docker/docker v20.10.7+incompatible => github.com/docker/docker v20.10.7+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/container -github.com/docker/docker/api/types/events -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/registry -github.com/docker/docker/api/types/strslice -github.com/docker/docker/api/types/swarm -github.com/docker/docker/api/types/swarm/runtime -github.com/docker/docker/api/types/time -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/pkg/jsonmessage -github.com/docker/docker/pkg/stdcopy -# github.com/docker/go-connections v0.4.0 => github.com/docker/go-connections v0.4.0 -## explicit -github.com/docker/go-connections/nat -github.com/docker/go-connections/sockets -github.com/docker/go-connections/tlsconfig # github.com/docker/go-units v0.4.0 => github.com/docker/go-units v0.4.0 ## explicit github.com/docker/go-units @@ -377,9 +337,6 @@ github.com/google/cadvisor/container/containerd/namespaces github.com/google/cadvisor/container/containerd/pkg/dialer github.com/google/cadvisor/container/crio github.com/google/cadvisor/container/crio/install -github.com/google/cadvisor/container/docker -github.com/google/cadvisor/container/docker/install -github.com/google/cadvisor/container/docker/utils github.com/google/cadvisor/container/libcontainer github.com/google/cadvisor/container/raw github.com/google/cadvisor/container/systemd @@ -410,7 +367,6 @@ github.com/google/cadvisor/utils/sysfs github.com/google/cadvisor/utils/sysinfo github.com/google/cadvisor/version github.com/google/cadvisor/watcher -github.com/google/cadvisor/zfs # github.com/google/cel-go v0.9.0 => github.com/google/cel-go v0.9.0 github.com/google/cel-go/cel github.com/google/cel-go/checker @@ -574,8 +530,6 @@ github.com/modern-go/reflect2 github.com/mohae/deepcopy # github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 => github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 github.com/monochromegane/go-gitignore -# github.com/morikuni/aec v1.0.0 => github.com/morikuni/aec v1.0.0 -github.com/morikuni/aec # github.com/mrunalp/fileutils v0.5.0 => github.com/mrunalp/fileutils v0.5.0 ## explicit github.com/mrunalp/fileutils @@ -638,11 +592,7 @@ github.com/onsi/gomega/matchers/support/goraph/node github.com/onsi/gomega/matchers/support/goraph/util github.com/onsi/gomega/types # github.com/opencontainers/go-digest v1.0.0 => github.com/opencontainers/go-digest v1.0.0 -## explicit github.com/opencontainers/go-digest -# github.com/opencontainers/image-spec v1.0.1 => github.com/opencontainers/image-spec v1.0.1 -github.com/opencontainers/image-spec/specs-go -github.com/opencontainers/image-spec/specs-go/v1 # github.com/opencontainers/runc v1.0.2 => github.com/opencontainers/runc v1.0.2 ## explicit github.com/opencontainers/runc/libcontainer @@ -1028,9 +978,7 @@ golang.org/x/net/http/httpguts golang.org/x/net/http2 golang.org/x/net/http2/hpack golang.org/x/net/idna -golang.org/x/net/internal/socks golang.org/x/net/internal/timeseries -golang.org/x/net/proxy golang.org/x/net/trace golang.org/x/net/websocket # golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f => golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f @@ -2353,7 +2301,6 @@ k8s.io/utils/io k8s.io/utils/keymutex k8s.io/utils/lru k8s.io/utils/net -k8s.io/utils/net/ebtables k8s.io/utils/nsenter k8s.io/utils/path k8s.io/utils/pointer @@ -2527,7 +2474,6 @@ sigs.k8s.io/yaml # github.com/containerd/go-runc => github.com/containerd/go-runc v1.0.0 # github.com/containerd/ttrpc => github.com/containerd/ttrpc v1.0.2 # github.com/containerd/typeurl => github.com/containerd/typeurl v1.0.2 -# github.com/containernetworking/cni => github.com/containernetworking/cni v0.8.1 # github.com/coredns/caddy => github.com/coredns/caddy v1.1.0 # github.com/coredns/corefile-migration => github.com/coredns/corefile-migration v1.0.14 # github.com/coreos/go-oidc => github.com/coreos/go-oidc v2.1.0+incompatible