mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-30 17:58:14 +00:00 
			
		
		
		
	Drop etcd tests dependency
This commit is contained in:
		
							
								
								
									
										206
									
								
								LICENSES/vendor/go.etcd.io/etcd/tests/v3/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										206
									
								
								LICENSES/vendor/go.etcd.io/etcd/tests/v3/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,206 +0,0 @@ | ||||
| = vendor/go.etcd.io/etcd/tests/v3 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/go.etcd.io/etcd/tests/v3/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 | ||||
							
								
								
									
										7
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								go.mod
									
									
									
									
									
								
							| @@ -232,7 +232,6 @@ replace ( | ||||
| 	github.com/emicklei/go-restful => github.com/emicklei/go-restful v2.9.5+incompatible | ||||
| 	github.com/envoyproxy/go-control-plane => github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d | ||||
| 	github.com/envoyproxy/protoc-gen-validate => github.com/envoyproxy/protoc-gen-validate v0.1.0 | ||||
| 	github.com/etcd-io/gofail => github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca | ||||
| 	github.com/euank/go-kmsg-parser => github.com/euank/go-kmsg-parser v2.0.0+incompatible | ||||
| 	github.com/evanphx/json-patch => github.com/evanphx/json-patch v4.11.0+incompatible | ||||
| 	github.com/exponent-io/jsonpath => github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d | ||||
| @@ -334,7 +333,7 @@ replace ( | ||||
| 	github.com/mailru/easyjson => github.com/mailru/easyjson v0.7.6 | ||||
| 	github.com/mattn/go-colorable => github.com/mattn/go-colorable v0.0.9 | ||||
| 	github.com/mattn/go-isatty => github.com/mattn/go-isatty v0.0.3 | ||||
| 	github.com/mattn/go-runewidth => github.com/mattn/go-runewidth v0.0.9 | ||||
| 	github.com/mattn/go-runewidth => github.com/mattn/go-runewidth v0.0.7 | ||||
| 	github.com/matttproud/golang_protobuf_extensions => github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 | ||||
| 	github.com/miekg/dns => github.com/miekg/dns v1.0.14 | ||||
| 	github.com/mindprince/gonvml => github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 | ||||
| @@ -362,7 +361,7 @@ replace ( | ||||
| 	github.com/mxk/go-flowrate => github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f | ||||
| 	github.com/niemeyer/pretty => github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e | ||||
| 	github.com/nxadm/tail => github.com/nxadm/tail v1.4.4 | ||||
| 	github.com/olekukonko/tablewriter => github.com/olekukonko/tablewriter v0.0.5 | ||||
| 	github.com/olekukonko/tablewriter => github.com/olekukonko/tablewriter v0.0.4 | ||||
| 	github.com/onsi/ginkgo => github.com/onsi/ginkgo v1.14.0 | ||||
| 	github.com/onsi/gomega => github.com/onsi/gomega v1.10.1 | ||||
| 	github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0 | ||||
| @@ -426,11 +425,9 @@ replace ( | ||||
| 	go.etcd.io/etcd/client/pkg/v3 => go.etcd.io/etcd/client/pkg/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/client/v2 => go.etcd.io/etcd/client/v2 v2.305.0 | ||||
| 	go.etcd.io/etcd/client/v3 => go.etcd.io/etcd/client/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/etcdutl/v3 => go.etcd.io/etcd/etcdutl/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/pkg/v3 => go.etcd.io/etcd/pkg/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/raft/v3 => go.etcd.io/etcd/raft/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/server/v3 => go.etcd.io/etcd/server/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/tests/v3 => go.etcd.io/etcd/tests/v3 v3.5.0 | ||||
| 	go.opencensus.io => go.opencensus.io v0.22.3 | ||||
| 	go.opentelemetry.io/contrib => go.opentelemetry.io/contrib v0.20.0 | ||||
| 	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 | ||||
|   | ||||
							
								
								
									
										8
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.sum
									
									
									
									
									
								
							| @@ -157,7 +157,6 @@ github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao | ||||
| github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/euank/go-kmsg-parser v2.0.0+incompatible h1:cHD53+PLQuuQyLZeriD1V/esuG4MuU0Pjs5y6iknohY= | ||||
| github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= | ||||
| @@ -316,7 +315,7 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= | ||||
| github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= | ||||
| @@ -364,7 +363,7 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb | ||||
| github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= | ||||
| github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= | ||||
| github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= | ||||
| github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= | ||||
| github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= | ||||
| @@ -473,15 +472,12 @@ go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLT | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0 h1:+uMuHYKKlLUzbW322XrQXbaGM9qiV7vUL+AEPT/KYY4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= | ||||
| go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
| go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= | ||||
|   | ||||
| @@ -115,7 +115,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||
| @@ -295,7 +294,6 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= | ||||
| @@ -328,7 +326,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA | ||||
| github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
| @@ -434,15 +431,12 @@ go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLT | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0 h1:+uMuHYKKlLUzbW322XrQXbaGM9qiV7vUL+AEPT/KYY4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
|   | ||||
| @@ -19,7 +19,6 @@ require ( | ||||
| 	github.com/google/gofuzz v1.1.0 | ||||
| 	github.com/google/uuid v1.1.2 | ||||
| 	github.com/googleapis/gnostic v0.5.5 | ||||
| 	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 | ||||
| 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 | ||||
| 	github.com/hashicorp/golang-lru v0.5.1 | ||||
| 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 | ||||
| @@ -30,7 +29,8 @@ require ( | ||||
| 	go.etcd.io/etcd/api/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/client/pkg/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/client/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/tests/v3 v3.5.0 | ||||
| 	go.etcd.io/etcd/server/v3 v3.5.0 | ||||
| 	go.uber.org/zap v1.17.0 | ||||
| 	golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 | ||||
| 	golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 | ||||
| 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c | ||||
|   | ||||
							
								
								
									
										6
									
								
								staging/src/k8s.io/apiserver/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								staging/src/k8s.io/apiserver/go.sum
									
									
									
										generated
									
									
									
								
							| @@ -115,7 +115,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||
| @@ -289,7 +288,6 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= | ||||
| @@ -321,7 +319,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA | ||||
| github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
| @@ -428,15 +425,12 @@ go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLT | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0 h1:+uMuHYKKlLUzbW322XrQXbaGM9qiV7vUL+AEPT/KYY4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
|   | ||||
							
								
								
									
										6
									
								
								staging/src/k8s.io/cloud-provider/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								staging/src/k8s.io/cloud-provider/go.sum
									
									
									
										generated
									
									
									
								
							| @@ -110,7 +110,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||
| @@ -283,7 +282,6 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= | ||||
| @@ -316,7 +314,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA | ||||
| github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
| @@ -422,15 +419,12 @@ go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLT | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0 h1:+uMuHYKKlLUzbW322XrQXbaGM9qiV7vUL+AEPT/KYY4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
|   | ||||
							
								
								
									
										6
									
								
								staging/src/k8s.io/controller-manager/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								staging/src/k8s.io/controller-manager/go.sum
									
									
									
										generated
									
									
									
								
							| @@ -145,7 +145,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||
| @@ -362,7 +361,6 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= | ||||
| @@ -404,7 +402,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA | ||||
| github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| @@ -539,15 +536,12 @@ go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLT | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0 h1:+uMuHYKKlLUzbW322XrQXbaGM9qiV7vUL+AEPT/KYY4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
|   | ||||
							
								
								
									
										6
									
								
								staging/src/k8s.io/kube-aggregator/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								staging/src/k8s.io/kube-aggregator/go.sum
									
									
									
										generated
									
									
									
								
							| @@ -109,7 +109,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||
| @@ -283,7 +282,6 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= | ||||
| @@ -317,7 +315,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA | ||||
| github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
| @@ -423,15 +420,12 @@ go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLT | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0 h1:+uMuHYKKlLUzbW322XrQXbaGM9qiV7vUL+AEPT/KYY4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
|   | ||||
| @@ -95,7 +95,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||
| github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= | ||||
| @@ -247,7 +246,6 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= | ||||
| github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= | ||||
| @@ -276,7 +274,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb | ||||
| github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
| @@ -364,11 +361,9 @@ go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQc | ||||
| go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
|   | ||||
							
								
								
									
										5
									
								
								staging/src/k8s.io/legacy-cloud-providers/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								staging/src/k8s.io/legacy-cloud-providers/go.sum
									
									
									
										generated
									
									
									
								
							| @@ -120,7 +120,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||
| @@ -292,7 +291,6 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= | ||||
| @@ -324,7 +322,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA | ||||
| github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
| @@ -425,11 +422,9 @@ go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQc | ||||
| go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
|   | ||||
							
								
								
									
										6
									
								
								staging/src/k8s.io/sample-apiserver/go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								staging/src/k8s.io/sample-apiserver/go.sum
									
									
									
										generated
									
									
									
								
							| @@ -108,7 +108,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= | ||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||
| github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= | ||||
| github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= | ||||
| github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||||
| @@ -282,7 +281,6 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA | ||||
| github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= | ||||
| github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||||
| github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||||
| github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= | ||||
| github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= | ||||
| @@ -314,7 +312,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA | ||||
| github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= | ||||
| github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
| github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
| @@ -420,15 +417,12 @@ go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLT | ||||
| go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= | ||||
| go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= | ||||
| go.etcd.io/etcd/etcdutl/v3 v3.5.0/go.mod h1:o98rKMCibbFAG8QS9KmvlYDGDShmmIbmRE8vSofzYNg= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= | ||||
| go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= | ||||
| go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= | ||||
| go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0 h1:+uMuHYKKlLUzbW322XrQXbaGM9qiV7vUL+AEPT/KYY4= | ||||
| go.etcd.io/etcd/tests/v3 v3.5.0/go.mod h1:f+mtZ1bE1YPvgKdOJV2BKy4JQW0nAFnQehgOE7+WyJE= | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
|   | ||||
							
								
								
									
										16
									
								
								vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/settable/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/settable/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,16 +0,0 @@ | ||||
| // | ||||
| /* | ||||
| grpc_logsettable contains a thread-safe wrapper around grpc-logging | ||||
| infrastructure. | ||||
|  | ||||
| The go-grpc assumes that logger can be only configured once as the `SetLoggerV2` | ||||
| method is: | ||||
| ```Not mutex-protected, should be called before any gRPC functions.``` | ||||
|  | ||||
| This package allows to supply parent logger once ("before any grpc"), but | ||||
| later change underlying implementation in thread-safe way when needed. | ||||
|  | ||||
| It's in particular useful for testing, where each testcase might need its own | ||||
| logger. | ||||
| */ | ||||
| package grpc_logsettable | ||||
							
								
								
									
										99
									
								
								vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/settable/logsettable.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										99
									
								
								vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/settable/logsettable.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,99 +0,0 @@ | ||||
| package grpc_logsettable | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"sync" | ||||
|  | ||||
| 	"google.golang.org/grpc/grpclog" | ||||
| ) | ||||
|  | ||||
| // SettableLoggerV2 is thread-safe. | ||||
| type SettableLoggerV2 interface { | ||||
| 	grpclog.LoggerV2 | ||||
| 	// Sets given logger as the underlying implementation. | ||||
| 	Set(loggerv2 grpclog.LoggerV2) | ||||
| 	// Sets `discard` logger as the underlying implementation. | ||||
| 	Reset() | ||||
| } | ||||
|  | ||||
| // ReplaceGrpcLoggerV2 creates and configures SettableLoggerV2 as grpc logger. | ||||
| func ReplaceGrpcLoggerV2() SettableLoggerV2 { | ||||
| 	settable := &settableLoggerV2{} | ||||
| 	settable.Reset() | ||||
| 	grpclog.SetLoggerV2(settable) | ||||
| 	return settable | ||||
| } | ||||
|  | ||||
| // SettableLoggerV2 implements SettableLoggerV2 | ||||
| type settableLoggerV2 struct { | ||||
| 	log grpclog.LoggerV2 | ||||
| 	mu  sync.RWMutex | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Set(log grpclog.LoggerV2) { | ||||
| 	s.mu.Lock() | ||||
| 	defer s.mu.Unlock() | ||||
| 	s.log = log | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Reset() { | ||||
| 	s.Set(grpclog.NewLoggerV2(ioutil.Discard, ioutil.Discard, ioutil.Discard)) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) get() grpclog.LoggerV2 { | ||||
| 	s.mu.RLock() | ||||
| 	defer s.mu.RUnlock() | ||||
| 	return s.log | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Info(args ...interface{}) { | ||||
| 	s.get().Info(args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Infoln(args ...interface{}) { | ||||
| 	s.get().Infoln(args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Infof(format string, args ...interface{}) { | ||||
| 	s.get().Infof(format, args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Warning(args ...interface{}) { | ||||
| 	s.get().Warning(args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Warningln(args ...interface{}) { | ||||
| 	s.get().Warningln(args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Warningf(format string, args ...interface{}) { | ||||
| 	s.get().Warningf(format, args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Error(args ...interface{}) { | ||||
| 	s.get().Error(args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Errorln(args ...interface{}) { | ||||
| 	s.get().Errorln(args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Errorf(format string, args ...interface{}) { | ||||
| 	s.get().Errorf(format, args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Fatal(args ...interface{}) { | ||||
| 	s.get().Fatal(args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Fatalln(args ...interface{}) { | ||||
| 	s.get().Fatalln(args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) Fatalf(format string, args ...interface{}) { | ||||
| 	s.get().Fatalf(format, args) | ||||
| } | ||||
|  | ||||
| func (s *settableLoggerV2) V(l int) bool { | ||||
| 	return s.get().V(l) | ||||
| } | ||||
							
								
								
									
										67
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/assert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										67
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/assert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,67 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 testutil | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func AssertEqual(t *testing.T, e, a interface{}, msg ...string) { | ||||
| 	t.Helper() | ||||
| 	if (e == nil || a == nil) && (isNil(e) && isNil(a)) { | ||||
| 		return | ||||
| 	} | ||||
| 	if reflect.DeepEqual(e, a) { | ||||
| 		return | ||||
| 	} | ||||
| 	s := "" | ||||
| 	if len(msg) > 1 { | ||||
| 		s = msg[0] + ": " | ||||
| 	} | ||||
| 	s = fmt.Sprintf("%sexpected %+v, got %+v", s, e, a) | ||||
| 	FatalStack(t, s) | ||||
| } | ||||
|  | ||||
| func AssertNil(t *testing.T, v interface{}) { | ||||
| 	t.Helper() | ||||
| 	AssertEqual(t, nil, v) | ||||
| } | ||||
|  | ||||
| func AssertNotNil(t *testing.T, v interface{}) { | ||||
| 	t.Helper() | ||||
| 	if v == nil { | ||||
| 		t.Fatalf("expected non-nil, got %+v", v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func AssertTrue(t *testing.T, v bool, msg ...string) { | ||||
| 	t.Helper() | ||||
| 	AssertEqual(t, true, v, msg...) | ||||
| } | ||||
|  | ||||
| func AssertFalse(t *testing.T, v bool, msg ...string) { | ||||
| 	t.Helper() | ||||
| 	AssertEqual(t, false, v, msg...) | ||||
| } | ||||
|  | ||||
| func isNil(v interface{}) bool { | ||||
| 	if v == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	rv := reflect.ValueOf(v) | ||||
| 	return rv.Kind() != reflect.Struct && rv.IsNil() | ||||
| } | ||||
							
								
								
									
										181
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/leak.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										181
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/leak.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,181 +0,0 @@ | ||||
| // Copyright 2013 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 testutil | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"regexp" | ||||
| 	"runtime" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // TODO: Replace with https://github.com/uber-go/goleak. | ||||
|  | ||||
| /* | ||||
| CheckLeakedGoroutine verifies tests do not leave any leaky | ||||
| goroutines. It returns true when there are goroutines still | ||||
| running(leaking) after all tests. | ||||
|  | ||||
| 	import "go.etcd.io/etcd/client/pkg/v3/testutil" | ||||
|  | ||||
| 	func TestMain(m *testing.M) { | ||||
| 		testutil.MustTestMainWithLeakDetection(m) | ||||
| 	} | ||||
|  | ||||
| 	func TestSample(t *testing.T) { | ||||
| 		RegisterLeakDetection(t) | ||||
| 		... | ||||
| 	} | ||||
| */ | ||||
| func CheckLeakedGoroutine() bool { | ||||
| 	gs := interestingGoroutines() | ||||
| 	if len(gs) == 0 { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	stackCount := make(map[string]int) | ||||
| 	re := regexp.MustCompile(`\(0[0-9a-fx, ]*\)`) | ||||
| 	for _, g := range gs { | ||||
| 		// strip out pointer arguments in first function of stack dump | ||||
| 		normalized := string(re.ReplaceAll([]byte(g), []byte("(...)"))) | ||||
| 		stackCount[normalized]++ | ||||
| 	} | ||||
|  | ||||
| 	fmt.Fprintf(os.Stderr, "Unexpected goroutines running after all test(s).\n") | ||||
| 	for stack, count := range stackCount { | ||||
| 		fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack) | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // CheckAfterTest returns an error if AfterTest would fail with an error. | ||||
| // Waits for go-routines shutdown for 'd'. | ||||
| func CheckAfterTest(d time.Duration) error { | ||||
| 	http.DefaultTransport.(*http.Transport).CloseIdleConnections() | ||||
| 	var bad string | ||||
| 	// Presence of these goroutines causes immediate test failure. | ||||
| 	badSubstring := map[string]string{ | ||||
| 		").writeLoop(": "a Transport", | ||||
| 		"created by net/http/httptest.(*Server).Start": "an httptest.Server", | ||||
| 		"timeoutHandler":        "a TimeoutHandler", | ||||
| 		"net.(*netFD).connect(": "a timing out dial", | ||||
| 		").noteClientGone(":     "a closenotifier sender", | ||||
| 		").readLoop(":           "a Transport", | ||||
| 		".grpc":                 "a gRPC resource", | ||||
| 		").sendCloseSubstream(": "a stream closing routine", | ||||
| 	} | ||||
|  | ||||
| 	var stacks string | ||||
| 	begin := time.Now() | ||||
| 	for time.Since(begin) < d { | ||||
| 		bad = "" | ||||
| 		goroutines := interestingGoroutines() | ||||
| 		if len(goroutines) == 0 { | ||||
| 			return nil | ||||
| 		} | ||||
| 		stacks = strings.Join(goroutines, "\n\n") | ||||
|  | ||||
| 		for substr, what := range badSubstring { | ||||
| 			if strings.Contains(stacks, substr) { | ||||
| 				bad = what | ||||
| 			} | ||||
| 		} | ||||
| 		// Undesired goroutines found, but goroutines might just still be | ||||
| 		// shutting down, so give it some time. | ||||
| 		runtime.Gosched() | ||||
| 		time.Sleep(50 * time.Millisecond) | ||||
| 	} | ||||
| 	return fmt.Errorf("appears to have leaked %s:\n%s", bad, stacks) | ||||
| } | ||||
|  | ||||
| // RegisterLeakDetection is a convenient way to register before-and-after code to a test. | ||||
| // If you execute RegisterLeakDetection, you don't need to explicitly register AfterTest. | ||||
| func RegisterLeakDetection(t TB) { | ||||
| 	if err := CheckAfterTest(10 * time.Millisecond); err != nil { | ||||
| 		t.Skip("Found leaked goroutined BEFORE test", err) | ||||
| 		return | ||||
| 	} | ||||
| 	t.Cleanup(func() { | ||||
| 		afterTest(t) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // afterTest is meant to run in a defer that executes after a test completes. | ||||
| // It will detect common goroutine leaks, retrying in case there are goroutines | ||||
| // not synchronously torn down, and fail the test if any goroutines are stuck. | ||||
| func afterTest(t TB) { | ||||
| 	// If test-failed the leaked goroutines list is hidding the real | ||||
| 	// source of problem. | ||||
| 	if !t.Failed() { | ||||
| 		if err := CheckAfterTest(1 * time.Second); err != nil { | ||||
| 			t.Errorf("Test %v", err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func interestingGoroutines() (gs []string) { | ||||
| 	buf := make([]byte, 2<<20) | ||||
| 	buf = buf[:runtime.Stack(buf, true)] | ||||
| 	for _, g := range strings.Split(string(buf), "\n\n") { | ||||
| 		sl := strings.SplitN(g, "\n", 2) | ||||
| 		if len(sl) != 2 { | ||||
| 			continue | ||||
| 		} | ||||
| 		stack := strings.TrimSpace(sl[1]) | ||||
| 		if stack == "" || | ||||
| 			strings.Contains(stack, "sync.(*WaitGroup).Done") || | ||||
| 			strings.Contains(stack, "os.(*file).close") || | ||||
| 			strings.Contains(stack, "os.(*Process).Release") || | ||||
| 			strings.Contains(stack, "created by os/signal.init") || | ||||
| 			strings.Contains(stack, "runtime/panic.go") || | ||||
| 			strings.Contains(stack, "created by testing.RunTests") || | ||||
| 			strings.Contains(stack, "created by testing.runTests") || | ||||
| 			strings.Contains(stack, "created by testing.(*T).Run") || | ||||
| 			strings.Contains(stack, "testing.Main(") || | ||||
| 			strings.Contains(stack, "runtime.goexit") || | ||||
| 			strings.Contains(stack, "go.etcd.io/etcd/client/pkg/v3/testutil.interestingGoroutines") || | ||||
| 			strings.Contains(stack, "go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop") || | ||||
| 			strings.Contains(stack, "github.com/golang/glog.(*loggingT).flushDaemon") || | ||||
| 			strings.Contains(stack, "created by runtime.gc") || | ||||
| 			strings.Contains(stack, "created by text/template/parse.lex") || | ||||
| 			strings.Contains(stack, "runtime.MHeap_Scavenger") || | ||||
| 			strings.Contains(stack, "rcrypto/internal/boring.(*PublicKeyRSA).finalize") || | ||||
| 			strings.Contains(stack, "net.(*netFD).Close(") || | ||||
| 			strings.Contains(stack, "testing.(*T).Run") { | ||||
| 			continue | ||||
| 		} | ||||
| 		gs = append(gs, stack) | ||||
| 	} | ||||
| 	sort.Strings(gs) | ||||
| 	return gs | ||||
| } | ||||
|  | ||||
| func MustCheckLeakedGoroutine() { | ||||
| 	http.DefaultTransport.(*http.Transport).CloseIdleConnections() | ||||
|  | ||||
| 	CheckAfterTest(5 * time.Second) | ||||
|  | ||||
| 	// Let the other goroutines finalize. | ||||
| 	runtime.Gosched() | ||||
|  | ||||
| 	if CheckLeakedGoroutine() { | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // MustTestMainWithLeakDetection expands standard m.Run with leaked | ||||
| // goroutines detection. | ||||
| func MustTestMainWithLeakDetection(m *testing.M) { | ||||
| 	v := m.Run() | ||||
| 	if v == 0 { | ||||
| 		MustCheckLeakedGoroutine() | ||||
| 	} | ||||
| 	os.Exit(v) | ||||
| } | ||||
							
								
								
									
										57
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/pauseable_handler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/pauseable_handler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,57 +0,0 @@ | ||||
| // Copyright 2015 The etcd 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 testutil | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| type PauseableHandler struct { | ||||
| 	Next   http.Handler | ||||
| 	mu     sync.Mutex | ||||
| 	paused bool | ||||
| } | ||||
|  | ||||
| func (ph *PauseableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||||
| 	ph.mu.Lock() | ||||
| 	paused := ph.paused | ||||
| 	ph.mu.Unlock() | ||||
| 	if !paused { | ||||
| 		ph.Next.ServeHTTP(w, r) | ||||
| 	} else { | ||||
| 		hj, ok := w.(http.Hijacker) | ||||
| 		if !ok { | ||||
| 			panic("webserver doesn't support hijacking") | ||||
| 		} | ||||
| 		conn, _, err := hj.Hijack() | ||||
| 		if err != nil { | ||||
| 			panic(err.Error()) | ||||
| 		} | ||||
| 		conn.Close() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (ph *PauseableHandler) Pause() { | ||||
| 	ph.mu.Lock() | ||||
| 	defer ph.mu.Unlock() | ||||
| 	ph.paused = true | ||||
| } | ||||
|  | ||||
| func (ph *PauseableHandler) Resume() { | ||||
| 	ph.mu.Lock() | ||||
| 	defer ph.mu.Unlock() | ||||
| 	ph.paused = false | ||||
| } | ||||
							
								
								
									
										139
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/recorder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										139
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/recorder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,139 +0,0 @@ | ||||
| // Copyright 2015 The etcd 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 testutil | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type Action struct { | ||||
| 	Name   string | ||||
| 	Params []interface{} | ||||
| } | ||||
|  | ||||
| type Recorder interface { | ||||
| 	// Record publishes an Action (e.g., function call) which will | ||||
| 	// be reflected by Wait() or Chan() | ||||
| 	Record(a Action) | ||||
| 	// Wait waits until at least n Actions are available or returns with error | ||||
| 	Wait(n int) ([]Action, error) | ||||
| 	// Action returns immediately available Actions | ||||
| 	Action() []Action | ||||
| 	// Chan returns the channel for actions published by Record | ||||
| 	Chan() <-chan Action | ||||
| } | ||||
|  | ||||
| // RecorderBuffered appends all Actions to a slice | ||||
| type RecorderBuffered struct { | ||||
| 	sync.Mutex | ||||
| 	actions []Action | ||||
| } | ||||
|  | ||||
| func (r *RecorderBuffered) Record(a Action) { | ||||
| 	r.Lock() | ||||
| 	r.actions = append(r.actions, a) | ||||
| 	r.Unlock() | ||||
| } | ||||
|  | ||||
| func (r *RecorderBuffered) Action() []Action { | ||||
| 	r.Lock() | ||||
| 	cpy := make([]Action, len(r.actions)) | ||||
| 	copy(cpy, r.actions) | ||||
| 	r.Unlock() | ||||
| 	return cpy | ||||
| } | ||||
|  | ||||
| func (r *RecorderBuffered) Wait(n int) (acts []Action, err error) { | ||||
| 	// legacy racey behavior | ||||
| 	WaitSchedule() | ||||
| 	acts = r.Action() | ||||
| 	if len(acts) < n { | ||||
| 		err = newLenErr(n, len(acts)) | ||||
| 	} | ||||
| 	return acts, err | ||||
| } | ||||
|  | ||||
| func (r *RecorderBuffered) Chan() <-chan Action { | ||||
| 	ch := make(chan Action) | ||||
| 	go func() { | ||||
| 		acts := r.Action() | ||||
| 		for i := range acts { | ||||
| 			ch <- acts[i] | ||||
| 		} | ||||
| 		close(ch) | ||||
| 	}() | ||||
| 	return ch | ||||
| } | ||||
|  | ||||
| // RecorderStream writes all Actions to an unbuffered channel | ||||
| type recorderStream struct { | ||||
| 	ch          chan Action | ||||
| 	waitTimeout time.Duration | ||||
| } | ||||
|  | ||||
| func NewRecorderStream() Recorder { | ||||
| 	return NewRecorderStreamWithWaitTimout(time.Duration(5 * time.Second)) | ||||
| } | ||||
|  | ||||
| func NewRecorderStreamWithWaitTimout(waitTimeout time.Duration) Recorder { | ||||
| 	return &recorderStream{ch: make(chan Action), waitTimeout: waitTimeout} | ||||
| } | ||||
|  | ||||
| func (r *recorderStream) Record(a Action) { | ||||
| 	r.ch <- a | ||||
| } | ||||
|  | ||||
| func (r *recorderStream) Action() (acts []Action) { | ||||
| 	for { | ||||
| 		select { | ||||
| 		case act := <-r.ch: | ||||
| 			acts = append(acts, act) | ||||
| 		default: | ||||
| 			return acts | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (r *recorderStream) Chan() <-chan Action { | ||||
| 	return r.ch | ||||
| } | ||||
|  | ||||
| func (r *recorderStream) Wait(n int) ([]Action, error) { | ||||
| 	acts := make([]Action, n) | ||||
| 	timeoutC := time.After(r.waitTimeout) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		select { | ||||
| 		case acts[i] = <-r.ch: | ||||
| 		case <-timeoutC: | ||||
| 			acts = acts[:i] | ||||
| 			return acts, newLenErr(n, i) | ||||
| 		} | ||||
| 	} | ||||
| 	// extra wait to catch any Action spew | ||||
| 	select { | ||||
| 	case act := <-r.ch: | ||||
| 		acts = append(acts, act) | ||||
| 	case <-time.After(10 * time.Millisecond): | ||||
| 	} | ||||
| 	return acts, nil | ||||
| } | ||||
|  | ||||
| func newLenErr(expected int, actual int) error { | ||||
| 	s := fmt.Sprintf("len(actions) = %d, expected >= %d", actual, expected) | ||||
| 	return errors.New(s) | ||||
| } | ||||
							
								
								
									
										130
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testingtb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										130
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testingtb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,130 +0,0 @@ | ||||
| // Copyright 2021 The etcd 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 testutil | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| // TB is a subset of methods of testing.TB interface. | ||||
| // We cannot implement testing.TB due to protection, so we expose this simplified interface. | ||||
| type TB interface { | ||||
| 	Cleanup(func()) | ||||
| 	Error(args ...interface{}) | ||||
| 	Errorf(format string, args ...interface{}) | ||||
| 	Fail() | ||||
| 	FailNow() | ||||
| 	Failed() bool | ||||
| 	Fatal(args ...interface{}) | ||||
| 	Fatalf(format string, args ...interface{}) | ||||
| 	Logf(format string, args ...interface{}) | ||||
| 	Name() string | ||||
| 	TempDir() string | ||||
| 	Helper() | ||||
| 	Skip(args ...interface{}) | ||||
| } | ||||
|  | ||||
| // NewTestingTBProthesis creates a fake variant of testing.TB implementation. | ||||
| // It's supposed to be used in contexts were real testing.T is not provided, | ||||
| // e.g. in 'examples'. | ||||
| // | ||||
| // The `closef` goroutine should get executed when tb will not be needed any longer. | ||||
| // | ||||
| // The provided implementation is NOT thread safe (Cleanup() method). | ||||
| func NewTestingTBProthesis(name string) (tb TB, closef func()) { | ||||
| 	testtb := &testingTBProthesis{name: name} | ||||
| 	return testtb, testtb.close | ||||
| } | ||||
|  | ||||
| type testingTBProthesis struct { | ||||
| 	name     string | ||||
| 	failed   bool | ||||
| 	cleanups []func() | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Helper() { | ||||
| 	// Ignored | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Skip(args ...interface{}) { | ||||
| 	t.Log(append([]interface{}{"Skipping due to: "}, args...)) | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Cleanup(f func()) { | ||||
| 	t.cleanups = append(t.cleanups, f) | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Error(args ...interface{}) { | ||||
| 	log.Println(args...) | ||||
| 	t.Fail() | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Errorf(format string, args ...interface{}) { | ||||
| 	log.Printf(format, args...) | ||||
| 	t.Fail() | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Fail() { | ||||
| 	t.failed = true | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) FailNow() { | ||||
| 	t.failed = true | ||||
| 	panic("FailNow() called") | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Failed() bool { | ||||
| 	return t.failed | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Fatal(args ...interface{}) { | ||||
| 	log.Fatalln(args...) | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Fatalf(format string, args ...interface{}) { | ||||
| 	log.Fatalf(format, args...) | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Logf(format string, args ...interface{}) { | ||||
| 	log.Printf(format, args...) | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Log(args ...interface{}) { | ||||
| 	log.Println(args...) | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) Name() string { | ||||
| 	return t.name | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) TempDir() string { | ||||
| 	dir, err := ioutil.TempDir("", t.name) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	t.cleanups = append([]func(){func() { | ||||
| 		t.Logf("Cleaning UP: %v", dir) | ||||
| 		os.RemoveAll(dir) | ||||
| 	}}, t.cleanups...) | ||||
| 	return dir | ||||
| } | ||||
|  | ||||
| func (t *testingTBProthesis) close() { | ||||
| 	for i := len(t.cleanups) - 1; i >= 0; i-- { | ||||
| 		t.cleanups[i]() | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										106
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testutil.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										106
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testutil.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,106 +0,0 @@ | ||||
| // Copyright 2015 The etcd 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 testutil provides test utility functions. | ||||
| package testutil | ||||
|  | ||||
| import ( | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // WaitSchedule briefly sleeps in order to invoke the go scheduler. | ||||
| // TODO: improve this when we are able to know the schedule or status of target go-routine. | ||||
| func WaitSchedule() { | ||||
| 	time.Sleep(10 * time.Millisecond) | ||||
| } | ||||
|  | ||||
| func MustNewURLs(t *testing.T, urls []string) []url.URL { | ||||
| 	if urls == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	var us []url.URL | ||||
| 	for _, url := range urls { | ||||
| 		u := MustNewURL(t, url) | ||||
| 		us = append(us, *u) | ||||
| 	} | ||||
| 	return us | ||||
| } | ||||
|  | ||||
| func MustNewURL(t *testing.T, s string) *url.URL { | ||||
| 	u, err := url.Parse(s) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("parse %v error: %v", s, err) | ||||
| 	} | ||||
| 	return u | ||||
| } | ||||
|  | ||||
| // FatalStack helps to fatal the test and print out the stacks of all running goroutines. | ||||
| func FatalStack(t *testing.T, s string) { | ||||
| 	stackTrace := make([]byte, 1024*1024) | ||||
| 	n := runtime.Stack(stackTrace, true) | ||||
| 	t.Errorf("---> Test failed: %s", s) | ||||
| 	t.Error(string(stackTrace[:n])) | ||||
| 	t.Fatal(s) | ||||
| } | ||||
|  | ||||
| // ConditionFunc returns true when a condition is met. | ||||
| type ConditionFunc func() (bool, error) | ||||
|  | ||||
| // Poll calls a condition function repeatedly on a polling interval until it returns true, returns an error | ||||
| // or the timeout is reached. If the condition function returns true or an error before the timeout, Poll | ||||
| // immediately returns with the true value or the error. If the timeout is exceeded, Poll returns false. | ||||
| func Poll(interval time.Duration, timeout time.Duration, condition ConditionFunc) (bool, error) { | ||||
| 	timeoutCh := time.After(timeout) | ||||
| 	ticker := time.NewTicker(interval) | ||||
| 	defer ticker.Stop() | ||||
|  | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-timeoutCh: | ||||
| 			return false, nil | ||||
| 		case <-ticker.C: | ||||
| 			success, err := condition() | ||||
| 			if err != nil { | ||||
| 				return false, err | ||||
| 			} | ||||
| 			if success { | ||||
| 				return true, nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func SkipTestIfShortMode(t TB, reason string) { | ||||
| 	if t != nil { | ||||
| 		t.Helper() | ||||
| 		if testing.Short() { | ||||
| 			t.Skip(reason) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ExitInShortMode closes the current process (with 0) if the short test mode detected. | ||||
| // | ||||
| // To be used in Test-main, where test context (testing.TB) is not available. | ||||
| // | ||||
| // Requires custom env-variable (GOLANG_TEST_SHORT) apart of `go test --short flag`. | ||||
| func ExitInShortMode(reason string) { | ||||
| 	if os.Getenv("GOLANG_TEST_SHORT") == "true" { | ||||
| 		os.Exit(0) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										22
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/var.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/go.etcd.io/etcd/client/pkg/v3/testutil/var.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,22 +0,0 @@ | ||||
| // Copyright 2018 The etcd 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 testutil | ||||
|  | ||||
| import "time" | ||||
|  | ||||
| var ( | ||||
| 	ApplyTimeout   = time.Second | ||||
| 	RequestTimeout = 3 * time.Second | ||||
| ) | ||||
							
								
								
									
										43
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,43 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 namespace is a clientv3 wrapper that translates all keys to begin | ||||
| // with a given prefix. | ||||
| // | ||||
| // First, create a client: | ||||
| // | ||||
| //	cli, err := clientv3.New(clientv3.Config{Endpoints: []string{"localhost:2379"}}) | ||||
| //	if err != nil { | ||||
| //		// handle error! | ||||
| //	} | ||||
| // | ||||
| // Next, override the client interfaces: | ||||
| // | ||||
| //	unprefixedKV := cli.KV | ||||
| //	cli.KV = namespace.NewKV(cli.KV, "my-prefix/") | ||||
| //	cli.Watcher = namespace.NewWatcher(cli.Watcher, "my-prefix/") | ||||
| //	cli.Lease = namespace.NewLease(cli.Lease, "my-prefix/") | ||||
| // | ||||
| // Now calls using 'cli' will namespace / prefix all keys with "my-prefix/": | ||||
| // | ||||
| //	cli.Put(context.TODO(), "abc", "123") | ||||
| //	resp, _ := unprefixedKV.Get(context.TODO(), "my-prefix/abc") | ||||
| //	fmt.Printf("%s\n", resp.Kvs[0].Value) | ||||
| //	// Output: 123 | ||||
| //	unprefixedKV.Put(context.TODO(), "my-prefix/abc", "456") | ||||
| //	resp, _ = cli.Get(context.TODO(), "abc") | ||||
| //	fmt.Printf("%s\n", resp.Kvs[0].Value) | ||||
| //	// Output: 456 | ||||
| // | ||||
| package namespace | ||||
							
								
								
									
										206
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/kv.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										206
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/kv.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,206 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 namespace | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/api/v3/v3rpc/rpctypes" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| ) | ||||
|  | ||||
| type kvPrefix struct { | ||||
| 	clientv3.KV | ||||
| 	pfx string | ||||
| } | ||||
|  | ||||
| // NewKV wraps a KV instance so that all requests | ||||
| // are prefixed with a given string. | ||||
| func NewKV(kv clientv3.KV, prefix string) clientv3.KV { | ||||
| 	return &kvPrefix{kv, prefix} | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) { | ||||
| 	if len(key) == 0 { | ||||
| 		return nil, rpctypes.ErrEmptyKey | ||||
| 	} | ||||
| 	op := kv.prefixOp(clientv3.OpPut(key, val, opts...)) | ||||
| 	r, err := kv.KV.Do(ctx, op) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	put := r.Put() | ||||
| 	kv.unprefixPutResponse(put) | ||||
| 	return put, nil | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) { | ||||
| 	if len(key) == 0 && !(clientv3.IsOptsWithFromKey(opts) || clientv3.IsOptsWithPrefix(opts)) { | ||||
| 		return nil, rpctypes.ErrEmptyKey | ||||
| 	} | ||||
| 	r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpGet(key, opts...))) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	get := r.Get() | ||||
| 	kv.unprefixGetResponse(get) | ||||
| 	return get, nil | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) { | ||||
| 	if len(key) == 0 && !(clientv3.IsOptsWithFromKey(opts) || clientv3.IsOptsWithPrefix(opts)) { | ||||
| 		return nil, rpctypes.ErrEmptyKey | ||||
| 	} | ||||
| 	r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpDelete(key, opts...))) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	del := r.Del() | ||||
| 	kv.unprefixDeleteResponse(del) | ||||
| 	return del, nil | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) { | ||||
| 	if len(op.KeyBytes()) == 0 && !op.IsTxn() { | ||||
| 		return clientv3.OpResponse{}, rpctypes.ErrEmptyKey | ||||
| 	} | ||||
| 	r, err := kv.KV.Do(ctx, kv.prefixOp(op)) | ||||
| 	if err != nil { | ||||
| 		return r, err | ||||
| 	} | ||||
| 	switch { | ||||
| 	case r.Get() != nil: | ||||
| 		kv.unprefixGetResponse(r.Get()) | ||||
| 	case r.Put() != nil: | ||||
| 		kv.unprefixPutResponse(r.Put()) | ||||
| 	case r.Del() != nil: | ||||
| 		kv.unprefixDeleteResponse(r.Del()) | ||||
| 	case r.Txn() != nil: | ||||
| 		kv.unprefixTxnResponse(r.Txn()) | ||||
| 	} | ||||
| 	return r, nil | ||||
| } | ||||
|  | ||||
| type txnPrefix struct { | ||||
| 	clientv3.Txn | ||||
| 	kv *kvPrefix | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) Txn(ctx context.Context) clientv3.Txn { | ||||
| 	return &txnPrefix{kv.KV.Txn(ctx), kv} | ||||
| } | ||||
|  | ||||
| func (txn *txnPrefix) If(cs ...clientv3.Cmp) clientv3.Txn { | ||||
| 	txn.Txn = txn.Txn.If(txn.kv.prefixCmps(cs)...) | ||||
| 	return txn | ||||
| } | ||||
|  | ||||
| func (txn *txnPrefix) Then(ops ...clientv3.Op) clientv3.Txn { | ||||
| 	txn.Txn = txn.Txn.Then(txn.kv.prefixOps(ops)...) | ||||
| 	return txn | ||||
| } | ||||
|  | ||||
| func (txn *txnPrefix) Else(ops ...clientv3.Op) clientv3.Txn { | ||||
| 	txn.Txn = txn.Txn.Else(txn.kv.prefixOps(ops)...) | ||||
| 	return txn | ||||
| } | ||||
|  | ||||
| func (txn *txnPrefix) Commit() (*clientv3.TxnResponse, error) { | ||||
| 	resp, err := txn.Txn.Commit() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	txn.kv.unprefixTxnResponse(resp) | ||||
| 	return resp, nil | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) prefixOp(op clientv3.Op) clientv3.Op { | ||||
| 	if !op.IsTxn() { | ||||
| 		begin, end := kv.prefixInterval(op.KeyBytes(), op.RangeBytes()) | ||||
| 		op.WithKeyBytes(begin) | ||||
| 		op.WithRangeBytes(end) | ||||
| 		return op | ||||
| 	} | ||||
| 	cmps, thenOps, elseOps := op.Txn() | ||||
| 	return clientv3.OpTxn(kv.prefixCmps(cmps), kv.prefixOps(thenOps), kv.prefixOps(elseOps)) | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) unprefixGetResponse(resp *clientv3.GetResponse) { | ||||
| 	for i := range resp.Kvs { | ||||
| 		resp.Kvs[i].Key = resp.Kvs[i].Key[len(kv.pfx):] | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) unprefixPutResponse(resp *clientv3.PutResponse) { | ||||
| 	if resp.PrevKv != nil { | ||||
| 		resp.PrevKv.Key = resp.PrevKv.Key[len(kv.pfx):] | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) unprefixDeleteResponse(resp *clientv3.DeleteResponse) { | ||||
| 	for i := range resp.PrevKvs { | ||||
| 		resp.PrevKvs[i].Key = resp.PrevKvs[i].Key[len(kv.pfx):] | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) unprefixTxnResponse(resp *clientv3.TxnResponse) { | ||||
| 	for _, r := range resp.Responses { | ||||
| 		switch tv := r.Response.(type) { | ||||
| 		case *pb.ResponseOp_ResponseRange: | ||||
| 			if tv.ResponseRange != nil { | ||||
| 				kv.unprefixGetResponse((*clientv3.GetResponse)(tv.ResponseRange)) | ||||
| 			} | ||||
| 		case *pb.ResponseOp_ResponsePut: | ||||
| 			if tv.ResponsePut != nil { | ||||
| 				kv.unprefixPutResponse((*clientv3.PutResponse)(tv.ResponsePut)) | ||||
| 			} | ||||
| 		case *pb.ResponseOp_ResponseDeleteRange: | ||||
| 			if tv.ResponseDeleteRange != nil { | ||||
| 				kv.unprefixDeleteResponse((*clientv3.DeleteResponse)(tv.ResponseDeleteRange)) | ||||
| 			} | ||||
| 		case *pb.ResponseOp_ResponseTxn: | ||||
| 			if tv.ResponseTxn != nil { | ||||
| 				kv.unprefixTxnResponse((*clientv3.TxnResponse)(tv.ResponseTxn)) | ||||
| 			} | ||||
| 		default: | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) prefixInterval(key, end []byte) (pfxKey []byte, pfxEnd []byte) { | ||||
| 	return prefixInterval(kv.pfx, key, end) | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) prefixCmps(cs []clientv3.Cmp) []clientv3.Cmp { | ||||
| 	newCmps := make([]clientv3.Cmp, len(cs)) | ||||
| 	for i := range cs { | ||||
| 		newCmps[i] = cs[i] | ||||
| 		pfxKey, endKey := kv.prefixInterval(cs[i].KeyBytes(), cs[i].RangeEnd) | ||||
| 		newCmps[i].WithKeyBytes(pfxKey) | ||||
| 		if len(cs[i].RangeEnd) != 0 { | ||||
| 			newCmps[i].RangeEnd = endKey | ||||
| 		} | ||||
| 	} | ||||
| 	return newCmps | ||||
| } | ||||
|  | ||||
| func (kv *kvPrefix) prefixOps(ops []clientv3.Op) []clientv3.Op { | ||||
| 	newOps := make([]clientv3.Op, len(ops)) | ||||
| 	for i := range ops { | ||||
| 		newOps[i] = kv.prefixOp(ops[i]) | ||||
| 	} | ||||
| 	return newOps | ||||
| } | ||||
							
								
								
									
										57
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/lease.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/lease.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,57 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 namespace | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| ) | ||||
|  | ||||
| type leasePrefix struct { | ||||
| 	clientv3.Lease | ||||
| 	pfx []byte | ||||
| } | ||||
|  | ||||
| // NewLease wraps a Lease interface to filter for only keys with a prefix | ||||
| // and remove that prefix when fetching attached keys through TimeToLive. | ||||
| func NewLease(l clientv3.Lease, prefix string) clientv3.Lease { | ||||
| 	return &leasePrefix{l, []byte(prefix)} | ||||
| } | ||||
|  | ||||
| func (l *leasePrefix) TimeToLive(ctx context.Context, id clientv3.LeaseID, opts ...clientv3.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) { | ||||
| 	resp, err := l.Lease.TimeToLive(ctx, id, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(resp.Keys) > 0 { | ||||
| 		var outKeys [][]byte | ||||
| 		for i := range resp.Keys { | ||||
| 			if len(resp.Keys[i]) < len(l.pfx) { | ||||
| 				// too short | ||||
| 				continue | ||||
| 			} | ||||
| 			if !bytes.Equal(resp.Keys[i][:len(l.pfx)], l.pfx) { | ||||
| 				// doesn't match prefix | ||||
| 				continue | ||||
| 			} | ||||
| 			// strip prefix | ||||
| 			outKeys = append(outKeys, resp.Keys[i][len(l.pfx):]) | ||||
| 		} | ||||
| 		resp.Keys = outKeys | ||||
| 	} | ||||
| 	return resp, nil | ||||
| } | ||||
							
								
								
									
										42
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,42 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 namespace | ||||
|  | ||||
| func prefixInterval(pfx string, key, end []byte) (pfxKey []byte, pfxEnd []byte) { | ||||
| 	pfxKey = make([]byte, len(pfx)+len(key)) | ||||
| 	copy(pfxKey[copy(pfxKey, pfx):], key) | ||||
|  | ||||
| 	if len(end) == 1 && end[0] == 0 { | ||||
| 		// the edge of the keyspace | ||||
| 		pfxEnd = make([]byte, len(pfx)) | ||||
| 		copy(pfxEnd, pfx) | ||||
| 		ok := false | ||||
| 		for i := len(pfxEnd) - 1; i >= 0; i-- { | ||||
| 			if pfxEnd[i]++; pfxEnd[i] != 0 { | ||||
| 				ok = true | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		if !ok { | ||||
| 			// 0xff..ff => 0x00 | ||||
| 			pfxEnd = []byte{0} | ||||
| 		} | ||||
| 	} else if len(end) >= 1 { | ||||
| 		pfxEnd = make([]byte, len(pfx)+len(end)) | ||||
| 		copy(pfxEnd[copy(pfxEnd, pfx):], end) | ||||
| 	} | ||||
|  | ||||
| 	return pfxKey, pfxEnd | ||||
| } | ||||
							
								
								
									
										83
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/watch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								vendor/go.etcd.io/etcd/client/v3/namespace/watch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,83 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 namespace | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| ) | ||||
|  | ||||
| type watcherPrefix struct { | ||||
| 	clientv3.Watcher | ||||
| 	pfx string | ||||
|  | ||||
| 	wg       sync.WaitGroup | ||||
| 	stopc    chan struct{} | ||||
| 	stopOnce sync.Once | ||||
| } | ||||
|  | ||||
| // NewWatcher wraps a Watcher instance so that all Watch requests | ||||
| // are prefixed with a given string and all Watch responses have | ||||
| // the prefix removed. | ||||
| func NewWatcher(w clientv3.Watcher, prefix string) clientv3.Watcher { | ||||
| 	return &watcherPrefix{Watcher: w, pfx: prefix, stopc: make(chan struct{})} | ||||
| } | ||||
|  | ||||
| func (w *watcherPrefix) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan { | ||||
| 	// since OpOption is opaque, determine range for prefixing through an OpGet | ||||
| 	op := clientv3.OpGet(key, opts...) | ||||
| 	end := op.RangeBytes() | ||||
| 	pfxBegin, pfxEnd := prefixInterval(w.pfx, []byte(key), end) | ||||
| 	if pfxEnd != nil { | ||||
| 		opts = append(opts, clientv3.WithRange(string(pfxEnd))) | ||||
| 	} | ||||
|  | ||||
| 	wch := w.Watcher.Watch(ctx, string(pfxBegin), opts...) | ||||
|  | ||||
| 	// translate watch events from prefixed to unprefixed | ||||
| 	pfxWch := make(chan clientv3.WatchResponse) | ||||
| 	w.wg.Add(1) | ||||
| 	go func() { | ||||
| 		defer func() { | ||||
| 			close(pfxWch) | ||||
| 			w.wg.Done() | ||||
| 		}() | ||||
| 		for wr := range wch { | ||||
| 			for i := range wr.Events { | ||||
| 				wr.Events[i].Kv.Key = wr.Events[i].Kv.Key[len(w.pfx):] | ||||
| 				if wr.Events[i].PrevKv != nil { | ||||
| 					wr.Events[i].PrevKv.Key = wr.Events[i].Kv.Key | ||||
| 				} | ||||
| 			} | ||||
| 			select { | ||||
| 			case pfxWch <- wr: | ||||
| 			case <-ctx.Done(): | ||||
| 				return | ||||
| 			case <-w.stopc: | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	return pfxWch | ||||
| } | ||||
|  | ||||
| func (w *watcherPrefix) Close() error { | ||||
| 	err := w.Watcher.Close() | ||||
| 	w.stopOnce.Do(func() { close(w.stopc) }) | ||||
| 	w.wg.Wait() | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										82
									
								
								vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,82 +0,0 @@ | ||||
| package endpoints | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	clientv3 "go.etcd.io/etcd/client/v3" | ||||
| ) | ||||
|  | ||||
| // Endpoint represents a single address the connection can be established with. | ||||
| // | ||||
| // Inspired by: https://pkg.go.dev/google.golang.org/grpc/resolver#Address. | ||||
| // Please document etcd version since which version each field is supported. | ||||
| type Endpoint struct { | ||||
| 	// Addr is the server address on which a connection will be established. | ||||
| 	// Since etcd 3.1 | ||||
| 	Addr string | ||||
|  | ||||
| 	// Metadata is the information associated with Addr, which may be used | ||||
| 	// to make load balancing decision. | ||||
| 	// Since etcd 3.1 | ||||
| 	Metadata interface{} | ||||
| } | ||||
|  | ||||
| type Operation uint8 | ||||
|  | ||||
| const ( | ||||
| 	// Add indicates an Endpoint is added. | ||||
| 	Add Operation = iota | ||||
| 	// Delete indicates an existing address is deleted. | ||||
| 	Delete | ||||
| ) | ||||
|  | ||||
| // Update describes a single edit action of an Endpoint. | ||||
| type Update struct { | ||||
| 	// Op - action Add or Delete. | ||||
| 	Op       Operation | ||||
| 	Key      string | ||||
| 	Endpoint Endpoint | ||||
| } | ||||
|  | ||||
| // WatchChannel is used to deliver notifications about endpoints updates. | ||||
| type WatchChannel <-chan []*Update | ||||
|  | ||||
| // Key2EndpointMap maps etcd key into struct describing the endpoint. | ||||
| type Key2EndpointMap map[string]Endpoint | ||||
|  | ||||
| // UpdateWithOpts describes endpoint update (add or delete) together | ||||
| // with etcd options (e.g. to attach an endpoint to a lease). | ||||
| type UpdateWithOpts struct { | ||||
| 	Update | ||||
| 	Opts []clientv3.OpOption | ||||
| } | ||||
|  | ||||
| // NewAddUpdateOpts constructs UpdateWithOpts for endpoint registration. | ||||
| func NewAddUpdateOpts(key string, endpoint Endpoint, opts ...clientv3.OpOption) *UpdateWithOpts { | ||||
| 	return &UpdateWithOpts{Update: Update{Op: Add, Key: key, Endpoint: endpoint}, Opts: opts} | ||||
| } | ||||
|  | ||||
| // NewDeleteUpdateOpts constructs UpdateWithOpts for endpoint deletion. | ||||
| func NewDeleteUpdateOpts(key string, opts ...clientv3.OpOption) *UpdateWithOpts { | ||||
| 	return &UpdateWithOpts{Update: Update{Op: Delete, Key: key}, Opts: opts} | ||||
| } | ||||
|  | ||||
| // Manager can be used to add/remove & inspect endpoints stored in etcd for | ||||
| // a particular target. | ||||
| type Manager interface { | ||||
| 	// Update allows to atomically add/remove a few endpoints from etcd. | ||||
| 	Update(ctx context.Context, updates []*UpdateWithOpts) error | ||||
|  | ||||
| 	// AddEndpoint registers a single endpoint in etcd. | ||||
| 	// For more advanced use-cases use the Update method. | ||||
| 	AddEndpoint(ctx context.Context, key string, endpoint Endpoint, opts ...clientv3.OpOption) error | ||||
| 	// DeleteEndpoint deletes a single endpoint stored in etcd. | ||||
| 	// For more advanced use-cases use the Update method. | ||||
| 	DeleteEndpoint(ctx context.Context, key string, opts ...clientv3.OpOption) error | ||||
|  | ||||
| 	// List returns all the endpoints for the current target as a map. | ||||
| 	List(ctx context.Context) (Key2EndpointMap, error) | ||||
| 	// NewWatchChannel creates a channel that populates or endpoint updates. | ||||
| 	// Cancel the 'ctx' to close the watcher. | ||||
| 	NewWatchChannel(ctx context.Context) (WatchChannel, error) | ||||
| } | ||||
							
								
								
									
										175
									
								
								vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints_impl.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										175
									
								
								vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints_impl.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,175 +0,0 @@ | ||||
| package endpoints | ||||
|  | ||||
| // TODO: The API is not yet implemented. | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"strings" | ||||
|  | ||||
| 	clientv3 "go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/client/v3/naming/endpoints/internal" | ||||
|  | ||||
| 	"go.uber.org/zap" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/status" | ||||
| ) | ||||
|  | ||||
| type endpointManager struct { | ||||
| 	// Client is an initialized etcd client. | ||||
| 	client *clientv3.Client | ||||
| 	target string | ||||
| } | ||||
|  | ||||
| // NewManager creates an endpoint manager which implements the interface of 'Manager'. | ||||
| func NewManager(client *clientv3.Client, target string) (Manager, error) { | ||||
| 	if client == nil { | ||||
| 		return nil, errors.New("invalid etcd client") | ||||
| 	} | ||||
|  | ||||
| 	if target == "" { | ||||
| 		return nil, errors.New("invalid target") | ||||
| 	} | ||||
|  | ||||
| 	em := &endpointManager{ | ||||
| 		client: client, | ||||
| 		target: target, | ||||
| 	} | ||||
| 	return em, nil | ||||
| } | ||||
|  | ||||
| func (m *endpointManager) Update(ctx context.Context, updates []*UpdateWithOpts) (err error) { | ||||
| 	ops := make([]clientv3.Op, 0, len(updates)) | ||||
| 	for _, update := range updates { | ||||
| 		if !strings.HasPrefix(update.Key, m.target+"/") { | ||||
| 			return status.Errorf(codes.InvalidArgument, "endpoints: endpoint key should be prefixed with '%s/' got: '%s'", m.target, update.Key) | ||||
| 		} | ||||
|  | ||||
| 		switch update.Op { | ||||
| 		case Add: | ||||
| 			internalUpdate := &internal.Update{ | ||||
| 				Op:       internal.Add, | ||||
| 				Addr:     update.Endpoint.Addr, | ||||
| 				Metadata: update.Endpoint.Metadata, | ||||
| 			} | ||||
|  | ||||
| 			var v []byte | ||||
| 			if v, err = json.Marshal(internalUpdate); err != nil { | ||||
| 				return status.Error(codes.InvalidArgument, err.Error()) | ||||
| 			} | ||||
| 			ops = append(ops, clientv3.OpPut(update.Key, string(v), update.Opts...)) | ||||
| 		case Delete: | ||||
| 			ops = append(ops, clientv3.OpDelete(update.Key, update.Opts...)) | ||||
| 		default: | ||||
| 			return status.Error(codes.InvalidArgument, "endpoints: bad update op") | ||||
| 		} | ||||
| 	} | ||||
| 	_, err = m.client.KV.Txn(ctx).Then(ops...).Commit() | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (m *endpointManager) AddEndpoint(ctx context.Context, key string, endpoint Endpoint, opts ...clientv3.OpOption) error { | ||||
| 	return m.Update(ctx, []*UpdateWithOpts{NewAddUpdateOpts(key, endpoint, opts...)}) | ||||
| } | ||||
|  | ||||
| func (m *endpointManager) DeleteEndpoint(ctx context.Context, key string, opts ...clientv3.OpOption) error { | ||||
| 	return m.Update(ctx, []*UpdateWithOpts{NewDeleteUpdateOpts(key, opts...)}) | ||||
| } | ||||
|  | ||||
| func (m *endpointManager) NewWatchChannel(ctx context.Context) (WatchChannel, error) { | ||||
| 	resp, err := m.client.Get(ctx, m.target, clientv3.WithPrefix(), clientv3.WithSerializable()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	lg := m.client.GetLogger() | ||||
| 	initUpdates := make([]*Update, 0, len(resp.Kvs)) | ||||
| 	for _, kv := range resp.Kvs { | ||||
| 		var iup internal.Update | ||||
| 		if err := json.Unmarshal(kv.Value, &iup); err != nil { | ||||
| 			lg.Warn("unmarshal endpoint update failed", zap.String("key", string(kv.Key)), zap.Error(err)) | ||||
| 			continue | ||||
| 		} | ||||
| 		up := &Update{ | ||||
| 			Op:       Add, | ||||
| 			Key:      string(kv.Key), | ||||
| 			Endpoint: Endpoint{Addr: iup.Addr, Metadata: iup.Metadata}, | ||||
| 		} | ||||
| 		initUpdates = append(initUpdates, up) | ||||
| 	} | ||||
|  | ||||
| 	upch := make(chan []*Update, 1) | ||||
| 	if len(initUpdates) > 0 { | ||||
| 		upch <- initUpdates | ||||
| 	} | ||||
| 	go m.watch(ctx, resp.Header.Revision+1, upch) | ||||
| 	return upch, nil | ||||
| } | ||||
|  | ||||
| func (m *endpointManager) watch(ctx context.Context, rev int64, upch chan []*Update) { | ||||
| 	defer close(upch) | ||||
|  | ||||
| 	lg := m.client.GetLogger() | ||||
| 	opts := []clientv3.OpOption{clientv3.WithRev(rev), clientv3.WithPrefix()} | ||||
| 	wch := m.client.Watch(ctx, m.target, opts...) | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-ctx.Done(): | ||||
| 			return | ||||
| 		case wresp, ok := <-wch: | ||||
| 			if !ok { | ||||
| 				lg.Warn("watch closed", zap.String("target", m.target)) | ||||
| 				return | ||||
| 			} | ||||
| 			if wresp.Err() != nil { | ||||
| 				lg.Warn("watch failed", zap.String("target", m.target), zap.Error(wresp.Err())) | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			deltaUps := make([]*Update, 0, len(wresp.Events)) | ||||
| 			for _, e := range wresp.Events { | ||||
| 				var iup internal.Update | ||||
| 				var err error | ||||
| 				var op Operation | ||||
| 				switch e.Type { | ||||
| 				case clientv3.EventTypePut: | ||||
| 					err = json.Unmarshal(e.Kv.Value, &iup) | ||||
| 					op = Add | ||||
| 					if err != nil { | ||||
| 						lg.Warn("unmarshal endpoint update failed", zap.String("key", string(e.Kv.Key)), zap.Error(err)) | ||||
| 						continue | ||||
| 					} | ||||
| 				case clientv3.EventTypeDelete: | ||||
| 					iup = internal.Update{Op: internal.Delete} | ||||
| 					op = Delete | ||||
| 				default: | ||||
| 					continue | ||||
| 				} | ||||
| 				up := &Update{Op: op, Key: string(e.Kv.Key), Endpoint: Endpoint{Addr: iup.Addr, Metadata: iup.Metadata}} | ||||
| 				deltaUps = append(deltaUps, up) | ||||
| 			} | ||||
| 			if len(deltaUps) > 0 { | ||||
| 				upch <- deltaUps | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (m *endpointManager) List(ctx context.Context) (Key2EndpointMap, error) { | ||||
| 	resp, err := m.client.Get(ctx, m.target, clientv3.WithPrefix(), clientv3.WithSerializable()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	eps := make(Key2EndpointMap) | ||||
| 	for _, kv := range resp.Kvs { | ||||
| 		var iup internal.Update | ||||
| 		if err := json.Unmarshal(kv.Value, &iup); err != nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		eps[string(kv.Key)] = Endpoint{Addr: iup.Addr, Metadata: iup.Metadata} | ||||
| 	} | ||||
| 	return eps, nil | ||||
| } | ||||
							
								
								
									
										38
									
								
								vendor/go.etcd.io/etcd/client/v3/naming/endpoints/internal/update.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/go.etcd.io/etcd/client/v3/naming/endpoints/internal/update.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,38 +0,0 @@ | ||||
| package internal | ||||
|  | ||||
| // Operation describes action performed on endpoint (addition vs deletion). | ||||
| // Must stay JSON-format compatible with: | ||||
| // https://pkg.go.dev/google.golang.org/grpc@v1.29.1/naming#Operation | ||||
| type Operation uint8 | ||||
|  | ||||
| const ( | ||||
| 	// Add indicates a new address is added. | ||||
| 	Add Operation = iota | ||||
| 	// Delete indicates an existing address is deleted. | ||||
| 	Delete | ||||
| ) | ||||
|  | ||||
| // Update defines a persistent (JSON marshalled) format representing | ||||
| // endpoint within the etcd storage. | ||||
| // | ||||
| // As the format can be persisted by one version of etcd client library and | ||||
| // read by other the format must be kept backward compatible and | ||||
| // in particular must be superset of the grpc(<=1.29.1) naming.Update structure: | ||||
| // https://pkg.go.dev/google.golang.org/grpc@v1.29.1/naming#Update | ||||
| // | ||||
| // Please document since which version of etcd-client given property is supported. | ||||
| // Please keep the naming consistent with e.g. https://pkg.go.dev/google.golang.org/grpc/resolver#Address. | ||||
| // | ||||
| // Notice that it is not valid having both empty string Addr and nil Metadata in an Update. | ||||
| type Update struct { | ||||
| 	// Op indicates the operation of the update. | ||||
| 	// Since etcd 3.1. | ||||
| 	Op Operation | ||||
| 	// Addr is the updated address. It is empty string if there is no address update. | ||||
| 	// Since etcd 3.1. | ||||
| 	Addr string | ||||
| 	// Metadata is the updated metadata. It is nil if there is no metadata update. | ||||
| 	// Metadata is not required for a custom naming implementation. | ||||
| 	// Since etcd 3.1. | ||||
| 	Metadata interface{} | ||||
| } | ||||
							
								
								
									
										115
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										115
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,115 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| ) | ||||
|  | ||||
| type AuthProxy struct { | ||||
| 	client *clientv3.Client | ||||
| } | ||||
|  | ||||
| func NewAuthProxy(c *clientv3.Client) pb.AuthServer { | ||||
| 	return &AuthProxy{client: c} | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) AuthEnable(ctx context.Context, r *pb.AuthEnableRequest) (*pb.AuthEnableResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).AuthEnable(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) AuthDisable(ctx context.Context, r *pb.AuthDisableRequest) (*pb.AuthDisableResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).AuthDisable(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) AuthStatus(ctx context.Context, r *pb.AuthStatusRequest) (*pb.AuthStatusResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).AuthStatus(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) Authenticate(ctx context.Context, r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).Authenticate(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).RoleAdd(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) RoleDelete(ctx context.Context, r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).RoleDelete(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) RoleGet(ctx context.Context, r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).RoleGet(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) RoleList(ctx context.Context, r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).RoleList(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) RoleRevokePermission(ctx context.Context, r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).RoleRevokePermission(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) RoleGrantPermission(ctx context.Context, r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).RoleGrantPermission(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) UserAdd(ctx context.Context, r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).UserAdd(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).UserDelete(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).UserGet(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) UserList(ctx context.Context, r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).UserList(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) UserGrantRole(ctx context.Context, r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).UserGrantRole(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) UserRevokeRole(ctx context.Context, r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).UserRevokeRole(ctx, r) | ||||
| } | ||||
|  | ||||
| func (ap *AuthProxy) UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) { | ||||
| 	conn := ap.client.ActiveConnection() | ||||
| 	return pb.NewAuthClient(conn).UserChangePassword(ctx, r) | ||||
| } | ||||
							
								
								
									
										172
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache/store.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										172
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache/store.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,172 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 cache exports functionality for efficiently caching and mapping | ||||
| // `RangeRequest`s to corresponding `RangeResponse`s. | ||||
| package cache | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/golang/groupcache/lru" | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/api/v3/v3rpc/rpctypes" | ||||
| 	"go.etcd.io/etcd/pkg/v3/adt" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	DefaultMaxEntries = 2048 | ||||
| 	ErrCompacted      = rpctypes.ErrGRPCCompacted | ||||
| ) | ||||
|  | ||||
| type Cache interface { | ||||
| 	Add(req *pb.RangeRequest, resp *pb.RangeResponse) | ||||
| 	Get(req *pb.RangeRequest) (*pb.RangeResponse, error) | ||||
| 	Compact(revision int64) | ||||
| 	Invalidate(key []byte, endkey []byte) | ||||
| 	Size() int | ||||
| 	Close() | ||||
| } | ||||
|  | ||||
| // keyFunc returns the key of a request, which is used to look up its caching response in the cache. | ||||
| func keyFunc(req *pb.RangeRequest) string { | ||||
| 	// TODO: use marshalTo to reduce allocation | ||||
| 	b, err := req.Marshal() | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return string(b) | ||||
| } | ||||
|  | ||||
| func NewCache(maxCacheEntries int) Cache { | ||||
| 	return &cache{ | ||||
| 		lru:          lru.New(maxCacheEntries), | ||||
| 		cachedRanges: adt.NewIntervalTree(), | ||||
| 		compactedRev: -1, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *cache) Close() {} | ||||
|  | ||||
| // cache implements Cache | ||||
| type cache struct { | ||||
| 	mu  sync.RWMutex | ||||
| 	lru *lru.Cache | ||||
|  | ||||
| 	// a reverse index for cache invalidation | ||||
| 	cachedRanges adt.IntervalTree | ||||
|  | ||||
| 	compactedRev int64 | ||||
| } | ||||
|  | ||||
| // Add adds the response of a request to the cache if its revision is larger than the compacted revision of the cache. | ||||
| func (c *cache) Add(req *pb.RangeRequest, resp *pb.RangeResponse) { | ||||
| 	key := keyFunc(req) | ||||
|  | ||||
| 	c.mu.Lock() | ||||
| 	defer c.mu.Unlock() | ||||
|  | ||||
| 	if req.Revision > c.compactedRev { | ||||
| 		c.lru.Add(key, resp) | ||||
| 	} | ||||
| 	// we do not need to invalidate a request with a revision specified. | ||||
| 	// so we do not need to add it into the reverse index. | ||||
| 	if req.Revision != 0 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		iv  *adt.IntervalValue | ||||
| 		ivl adt.Interval | ||||
| 	) | ||||
| 	if len(req.RangeEnd) != 0 { | ||||
| 		ivl = adt.NewStringAffineInterval(string(req.Key), string(req.RangeEnd)) | ||||
| 	} else { | ||||
| 		ivl = adt.NewStringAffinePoint(string(req.Key)) | ||||
| 	} | ||||
|  | ||||
| 	iv = c.cachedRanges.Find(ivl) | ||||
|  | ||||
| 	if iv == nil { | ||||
| 		val := map[string]struct{}{key: {}} | ||||
| 		c.cachedRanges.Insert(ivl, val) | ||||
| 	} else { | ||||
| 		val := iv.Val.(map[string]struct{}) | ||||
| 		val[key] = struct{}{} | ||||
| 		iv.Val = val | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Get looks up the caching response for a given request. | ||||
| // Get is also responsible for lazy eviction when accessing compacted entries. | ||||
| func (c *cache) Get(req *pb.RangeRequest) (*pb.RangeResponse, error) { | ||||
| 	key := keyFunc(req) | ||||
|  | ||||
| 	c.mu.Lock() | ||||
| 	defer c.mu.Unlock() | ||||
|  | ||||
| 	if req.Revision > 0 && req.Revision < c.compactedRev { | ||||
| 		c.lru.Remove(key) | ||||
| 		return nil, ErrCompacted | ||||
| 	} | ||||
|  | ||||
| 	if resp, ok := c.lru.Get(key); ok { | ||||
| 		return resp.(*pb.RangeResponse), nil | ||||
| 	} | ||||
| 	return nil, errors.New("not exist") | ||||
| } | ||||
|  | ||||
| // Invalidate invalidates the cache entries that intersecting with the given range from key to endkey. | ||||
| func (c *cache) Invalidate(key, endkey []byte) { | ||||
| 	c.mu.Lock() | ||||
| 	defer c.mu.Unlock() | ||||
|  | ||||
| 	var ( | ||||
| 		ivs []*adt.IntervalValue | ||||
| 		ivl adt.Interval | ||||
| 	) | ||||
| 	if len(endkey) == 0 { | ||||
| 		ivl = adt.NewStringAffinePoint(string(key)) | ||||
| 	} else { | ||||
| 		ivl = adt.NewStringAffineInterval(string(key), string(endkey)) | ||||
| 	} | ||||
|  | ||||
| 	ivs = c.cachedRanges.Stab(ivl) | ||||
| 	for _, iv := range ivs { | ||||
| 		keys := iv.Val.(map[string]struct{}) | ||||
| 		for key := range keys { | ||||
| 			c.lru.Remove(key) | ||||
| 		} | ||||
| 	} | ||||
| 	// delete after removing all keys since it is destructive to 'ivs' | ||||
| 	c.cachedRanges.Delete(ivl) | ||||
| } | ||||
|  | ||||
| // Compact invalidate all caching response before the given rev. | ||||
| // Replace with the invalidation is lazy. The actual removal happens when the entries is accessed. | ||||
| func (c *cache) Compact(revision int64) { | ||||
| 	c.mu.Lock() | ||||
| 	defer c.mu.Unlock() | ||||
|  | ||||
| 	if revision > c.compactedRev { | ||||
| 		c.compactedRev = revision | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *cache) Size() int { | ||||
| 	c.mu.RLock() | ||||
| 	defer c.mu.RUnlock() | ||||
| 	return c.lru.Len() | ||||
| } | ||||
							
								
								
									
										213
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cluster.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										213
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cluster.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,213 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"sync" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/client/v3/naming/endpoints" | ||||
| 	"golang.org/x/time/rate" | ||||
|  | ||||
| 	"go.uber.org/zap" | ||||
| ) | ||||
|  | ||||
| // allow maximum 1 retry per second | ||||
| const resolveRetryRate = 1 | ||||
|  | ||||
| type clusterProxy struct { | ||||
| 	lg   *zap.Logger | ||||
| 	clus clientv3.Cluster | ||||
| 	ctx  context.Context | ||||
|  | ||||
| 	// advertise client URL | ||||
| 	advaddr string | ||||
| 	prefix  string | ||||
|  | ||||
| 	em endpoints.Manager | ||||
|  | ||||
| 	umu  sync.RWMutex | ||||
| 	umap map[string]endpoints.Endpoint | ||||
| } | ||||
|  | ||||
| // NewClusterProxy takes optional prefix to fetch grpc-proxy member endpoints. | ||||
| // The returned channel is closed when there is grpc-proxy endpoint registered | ||||
| // and the client's context is canceled so the 'register' loop returns. | ||||
| // TODO: Expand the API to report creation errors | ||||
| func NewClusterProxy(lg *zap.Logger, c *clientv3.Client, advaddr string, prefix string) (pb.ClusterServer, <-chan struct{}) { | ||||
| 	if lg == nil { | ||||
| 		lg = zap.NewNop() | ||||
| 	} | ||||
|  | ||||
| 	var em endpoints.Manager | ||||
| 	if advaddr != "" && prefix != "" { | ||||
| 		var err error | ||||
| 		if em, err = endpoints.NewManager(c, prefix); err != nil { | ||||
| 			lg.Error("failed to provision endpointsManager", zap.String("prefix", prefix), zap.Error(err)) | ||||
| 			return nil, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	cp := &clusterProxy{ | ||||
| 		lg:   lg, | ||||
| 		clus: c.Cluster, | ||||
| 		ctx:  c.Ctx(), | ||||
|  | ||||
| 		advaddr: advaddr, | ||||
| 		prefix:  prefix, | ||||
| 		umap:    make(map[string]endpoints.Endpoint), | ||||
| 		em:      em, | ||||
| 	} | ||||
|  | ||||
| 	donec := make(chan struct{}) | ||||
| 	if em != nil { | ||||
| 		go func() { | ||||
| 			defer close(donec) | ||||
| 			cp.establishEndpointWatch(prefix) | ||||
| 		}() | ||||
| 		return cp, donec | ||||
| 	} | ||||
|  | ||||
| 	close(donec) | ||||
| 	return cp, donec | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) establishEndpointWatch(prefix string) { | ||||
| 	rm := rate.NewLimiter(rate.Limit(resolveRetryRate), resolveRetryRate) | ||||
| 	for rm.Wait(cp.ctx) == nil { | ||||
| 		wc, err := cp.em.NewWatchChannel(cp.ctx) | ||||
| 		if err != nil { | ||||
| 			cp.lg.Warn("failed to establish endpoint watch", zap.String("prefix", prefix), zap.Error(err)) | ||||
| 			continue | ||||
| 		} | ||||
| 		cp.monitor(wc) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) monitor(wa endpoints.WatchChannel) { | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-cp.ctx.Done(): | ||||
| 			cp.lg.Info("watching endpoints interrupted", zap.Error(cp.ctx.Err())) | ||||
| 			return | ||||
| 		case updates := <-wa: | ||||
| 			cp.umu.Lock() | ||||
| 			for _, up := range updates { | ||||
| 				switch up.Op { | ||||
| 				case endpoints.Add: | ||||
| 					cp.umap[up.Endpoint.Addr] = up.Endpoint | ||||
| 				case endpoints.Delete: | ||||
| 					delete(cp.umap, up.Endpoint.Addr) | ||||
| 				} | ||||
| 			} | ||||
| 			cp.umu.Unlock() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) (*pb.MemberAddResponse, error) { | ||||
| 	if r.IsLearner { | ||||
| 		return cp.memberAddAsLearner(ctx, r.PeerURLs) | ||||
| 	} | ||||
| 	return cp.memberAdd(ctx, r.PeerURLs) | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) memberAdd(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) { | ||||
| 	mresp, err := cp.clus.MemberAdd(ctx, peerURLs) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	resp := (pb.MemberAddResponse)(*mresp) | ||||
| 	return &resp, err | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) memberAddAsLearner(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) { | ||||
| 	mresp, err := cp.clus.MemberAddAsLearner(ctx, peerURLs) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	resp := (pb.MemberAddResponse)(*mresp) | ||||
| 	return &resp, err | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) MemberRemove(ctx context.Context, r *pb.MemberRemoveRequest) (*pb.MemberRemoveResponse, error) { | ||||
| 	mresp, err := cp.clus.MemberRemove(ctx, r.ID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	resp := (pb.MemberRemoveResponse)(*mresp) | ||||
| 	return &resp, err | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) MemberUpdate(ctx context.Context, r *pb.MemberUpdateRequest) (*pb.MemberUpdateResponse, error) { | ||||
| 	mresp, err := cp.clus.MemberUpdate(ctx, r.ID, r.PeerURLs) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	resp := (pb.MemberUpdateResponse)(*mresp) | ||||
| 	return &resp, err | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) membersFromUpdates() ([]*pb.Member, error) { | ||||
| 	cp.umu.RLock() | ||||
| 	defer cp.umu.RUnlock() | ||||
| 	mbs := make([]*pb.Member, 0, len(cp.umap)) | ||||
| 	for addr, upt := range cp.umap { | ||||
| 		m, err := decodeMeta(fmt.Sprint(upt.Metadata)) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		mbs = append(mbs, &pb.Member{Name: m.Name, ClientURLs: []string{addr}}) | ||||
| 	} | ||||
| 	return mbs, nil | ||||
| } | ||||
|  | ||||
| // MemberList wraps member list API with following rules: | ||||
| // - If 'advaddr' is not empty and 'prefix' is not empty, return registered member lists via resolver | ||||
| // - If 'advaddr' is not empty and 'prefix' is not empty and registered grpc-proxy members haven't been fetched, return the 'advaddr' | ||||
| // - If 'advaddr' is not empty and 'prefix' is empty, return 'advaddr' without forcing it to 'register' | ||||
| // - If 'advaddr' is empty, forward to member list API | ||||
| func (cp *clusterProxy) MemberList(ctx context.Context, r *pb.MemberListRequest) (*pb.MemberListResponse, error) { | ||||
| 	if cp.advaddr != "" { | ||||
| 		if cp.prefix != "" { | ||||
| 			mbs, err := cp.membersFromUpdates() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			if len(mbs) > 0 { | ||||
| 				return &pb.MemberListResponse{Members: mbs}, nil | ||||
| 			} | ||||
| 		} | ||||
| 		// prefix is empty or no grpc-proxy members haven't been registered | ||||
| 		hostname, _ := os.Hostname() | ||||
| 		return &pb.MemberListResponse{Members: []*pb.Member{{Name: hostname, ClientURLs: []string{cp.advaddr}}}}, nil | ||||
| 	} | ||||
| 	mresp, err := cp.clus.MemberList(ctx) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	resp := (pb.MemberListResponse)(*mresp) | ||||
| 	return &resp, err | ||||
| } | ||||
|  | ||||
| func (cp *clusterProxy) MemberPromote(ctx context.Context, r *pb.MemberPromoteRequest) (*pb.MemberPromoteResponse, error) { | ||||
| 	// TODO: implement | ||||
| 	return nil, errors.New("not implemented") | ||||
| } | ||||
							
								
								
									
										16
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,16 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy is an OSI level 7 proxy for etcd v3 API requests. | ||||
| package grpcproxy | ||||
							
								
								
									
										65
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/election.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										65
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/election.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,65 +0,0 @@ | ||||
| // Copyright 2017 The etcd Lockors | ||||
| // | ||||
| // 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb" | ||||
| ) | ||||
|  | ||||
| type electionProxy struct { | ||||
| 	client *clientv3.Client | ||||
| } | ||||
|  | ||||
| func NewElectionProxy(client *clientv3.Client) v3electionpb.ElectionServer { | ||||
| 	return &electionProxy{client: client} | ||||
| } | ||||
|  | ||||
| func (ep *electionProxy) Campaign(ctx context.Context, req *v3electionpb.CampaignRequest) (*v3electionpb.CampaignResponse, error) { | ||||
| 	return v3electionpb.NewElectionClient(ep.client.ActiveConnection()).Campaign(ctx, req) | ||||
| } | ||||
|  | ||||
| func (ep *electionProxy) Proclaim(ctx context.Context, req *v3electionpb.ProclaimRequest) (*v3electionpb.ProclaimResponse, error) { | ||||
| 	return v3electionpb.NewElectionClient(ep.client.ActiveConnection()).Proclaim(ctx, req) | ||||
| } | ||||
|  | ||||
| func (ep *electionProxy) Leader(ctx context.Context, req *v3electionpb.LeaderRequest) (*v3electionpb.LeaderResponse, error) { | ||||
| 	return v3electionpb.NewElectionClient(ep.client.ActiveConnection()).Leader(ctx, req) | ||||
| } | ||||
|  | ||||
| func (ep *electionProxy) Observe(req *v3electionpb.LeaderRequest, s v3electionpb.Election_ObserveServer) error { | ||||
| 	conn := ep.client.ActiveConnection() | ||||
| 	ctx, cancel := context.WithCancel(s.Context()) | ||||
| 	defer cancel() | ||||
| 	sc, err := v3electionpb.NewElectionClient(conn).Observe(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for { | ||||
| 		rr, err := sc.Recv() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err = s.Send(rr); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (ep *electionProxy) Resign(ctx context.Context, req *v3electionpb.ResignRequest) (*v3electionpb.ResignResponse, error) { | ||||
| 	return v3electionpb.NewElectionClient(ep.client.ActiveConnection()).Resign(ctx, req) | ||||
| } | ||||
							
								
								
									
										76
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/health.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										76
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/health.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,76 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"time" | ||||
|  | ||||
| 	"go.etcd.io/etcd/api/v3/v3rpc/rpctypes" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" | ||||
| 	"go.uber.org/zap" | ||||
| ) | ||||
|  | ||||
| // HandleHealth registers health handler on '/health'. | ||||
| func HandleHealth(lg *zap.Logger, mux *http.ServeMux, c *clientv3.Client) { | ||||
| 	if lg == nil { | ||||
| 		lg = zap.NewNop() | ||||
| 	} | ||||
| 	mux.Handle(etcdhttp.PathHealth, etcdhttp.NewHealthHandler(lg, func(excludedAlarms etcdhttp.AlarmSet) etcdhttp.Health { return checkHealth(c) })) | ||||
| } | ||||
|  | ||||
| // HandleProxyHealth registers health handler on '/proxy/health'. | ||||
| func HandleProxyHealth(lg *zap.Logger, mux *http.ServeMux, c *clientv3.Client) { | ||||
| 	if lg == nil { | ||||
| 		lg = zap.NewNop() | ||||
| 	} | ||||
| 	mux.Handle(etcdhttp.PathProxyHealth, etcdhttp.NewHealthHandler(lg, func(excludedAlarms etcdhttp.AlarmSet) etcdhttp.Health { return checkProxyHealth(c) })) | ||||
| } | ||||
|  | ||||
| func checkHealth(c *clientv3.Client) etcdhttp.Health { | ||||
| 	h := etcdhttp.Health{Health: "false"} | ||||
| 	ctx, cancel := context.WithTimeout(c.Ctx(), time.Second) | ||||
| 	_, err := c.Get(ctx, "a") | ||||
| 	cancel() | ||||
| 	if err == nil || err == rpctypes.ErrPermissionDenied { | ||||
| 		h.Health = "true" | ||||
| 	} else { | ||||
| 		h.Reason = fmt.Sprintf("GET ERROR:%s", err) | ||||
| 	} | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| func checkProxyHealth(c *clientv3.Client) etcdhttp.Health { | ||||
| 	if c == nil { | ||||
| 		return etcdhttp.Health{Health: "false", Reason: "no connection to proxy"} | ||||
| 	} | ||||
| 	h := checkHealth(c) | ||||
| 	if h.Health != "true" { | ||||
| 		return h | ||||
| 	} | ||||
| 	ctx, cancel := context.WithTimeout(c.Ctx(), time.Second*3) | ||||
| 	ch := c.Watch(ctx, "a", clientv3.WithCreatedNotify()) | ||||
| 	select { | ||||
| 	case <-ch: | ||||
| 	case <-ctx.Done(): | ||||
| 		h.Health = "false" | ||||
| 		h.Reason = "WATCH TIMEOUT" | ||||
| 	} | ||||
| 	cancel() | ||||
| 	return h | ||||
| } | ||||
							
								
								
									
										232
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/kv.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										232
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/kv.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,232 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache" | ||||
| ) | ||||
|  | ||||
| type kvProxy struct { | ||||
| 	kv    clientv3.KV | ||||
| 	cache cache.Cache | ||||
| } | ||||
|  | ||||
| func NewKvProxy(c *clientv3.Client) (pb.KVServer, <-chan struct{}) { | ||||
| 	kv := &kvProxy{ | ||||
| 		kv:    c.KV, | ||||
| 		cache: cache.NewCache(cache.DefaultMaxEntries), | ||||
| 	} | ||||
| 	donec := make(chan struct{}) | ||||
| 	close(donec) | ||||
| 	return kv, donec | ||||
| } | ||||
|  | ||||
| func (p *kvProxy) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) { | ||||
| 	if r.Serializable { | ||||
| 		resp, err := p.cache.Get(r) | ||||
| 		switch err { | ||||
| 		case nil: | ||||
| 			cacheHits.Inc() | ||||
| 			return resp, nil | ||||
| 		case cache.ErrCompacted: | ||||
| 			cacheHits.Inc() | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		cachedMisses.Inc() | ||||
| 	} | ||||
|  | ||||
| 	resp, err := p.kv.Do(ctx, RangeRequestToOp(r)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// cache linearizable as serializable | ||||
| 	req := *r | ||||
| 	req.Serializable = true | ||||
| 	gresp := (*pb.RangeResponse)(resp.Get()) | ||||
| 	p.cache.Add(&req, gresp) | ||||
| 	cacheKeys.Set(float64(p.cache.Size())) | ||||
|  | ||||
| 	return gresp, nil | ||||
| } | ||||
|  | ||||
| func (p *kvProxy) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) { | ||||
| 	p.cache.Invalidate(r.Key, nil) | ||||
| 	cacheKeys.Set(float64(p.cache.Size())) | ||||
|  | ||||
| 	resp, err := p.kv.Do(ctx, PutRequestToOp(r)) | ||||
| 	return (*pb.PutResponse)(resp.Put()), err | ||||
| } | ||||
|  | ||||
| func (p *kvProxy) DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) { | ||||
| 	p.cache.Invalidate(r.Key, r.RangeEnd) | ||||
| 	cacheKeys.Set(float64(p.cache.Size())) | ||||
|  | ||||
| 	resp, err := p.kv.Do(ctx, DelRequestToOp(r)) | ||||
| 	return (*pb.DeleteRangeResponse)(resp.Del()), err | ||||
| } | ||||
|  | ||||
| func (p *kvProxy) txnToCache(reqs []*pb.RequestOp, resps []*pb.ResponseOp) { | ||||
| 	for i := range resps { | ||||
| 		switch tv := resps[i].Response.(type) { | ||||
| 		case *pb.ResponseOp_ResponsePut: | ||||
| 			p.cache.Invalidate(reqs[i].GetRequestPut().Key, nil) | ||||
| 		case *pb.ResponseOp_ResponseDeleteRange: | ||||
| 			rdr := reqs[i].GetRequestDeleteRange() | ||||
| 			p.cache.Invalidate(rdr.Key, rdr.RangeEnd) | ||||
| 		case *pb.ResponseOp_ResponseRange: | ||||
| 			req := *(reqs[i].GetRequestRange()) | ||||
| 			req.Serializable = true | ||||
| 			p.cache.Add(&req, tv.ResponseRange) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *kvProxy) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) { | ||||
| 	op := TxnRequestToOp(r) | ||||
| 	opResp, err := p.kv.Do(ctx, op) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	resp := opResp.Txn() | ||||
|  | ||||
| 	// txn may claim an outdated key is updated; be safe and invalidate | ||||
| 	for _, cmp := range r.Compare { | ||||
| 		p.cache.Invalidate(cmp.Key, cmp.RangeEnd) | ||||
| 	} | ||||
| 	// update any fetched keys | ||||
| 	if resp.Succeeded { | ||||
| 		p.txnToCache(r.Success, resp.Responses) | ||||
| 	} else { | ||||
| 		p.txnToCache(r.Failure, resp.Responses) | ||||
| 	} | ||||
|  | ||||
| 	cacheKeys.Set(float64(p.cache.Size())) | ||||
|  | ||||
| 	return (*pb.TxnResponse)(resp), nil | ||||
| } | ||||
|  | ||||
| func (p *kvProxy) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error) { | ||||
| 	var opts []clientv3.CompactOption | ||||
| 	if r.Physical { | ||||
| 		opts = append(opts, clientv3.WithCompactPhysical()) | ||||
| 	} | ||||
|  | ||||
| 	resp, err := p.kv.Compact(ctx, r.Revision, opts...) | ||||
| 	if err == nil { | ||||
| 		p.cache.Compact(r.Revision) | ||||
| 	} | ||||
|  | ||||
| 	cacheKeys.Set(float64(p.cache.Size())) | ||||
|  | ||||
| 	return (*pb.CompactionResponse)(resp), err | ||||
| } | ||||
|  | ||||
| func requestOpToOp(union *pb.RequestOp) clientv3.Op { | ||||
| 	switch tv := union.Request.(type) { | ||||
| 	case *pb.RequestOp_RequestRange: | ||||
| 		if tv.RequestRange != nil { | ||||
| 			return RangeRequestToOp(tv.RequestRange) | ||||
| 		} | ||||
| 	case *pb.RequestOp_RequestPut: | ||||
| 		if tv.RequestPut != nil { | ||||
| 			return PutRequestToOp(tv.RequestPut) | ||||
| 		} | ||||
| 	case *pb.RequestOp_RequestDeleteRange: | ||||
| 		if tv.RequestDeleteRange != nil { | ||||
| 			return DelRequestToOp(tv.RequestDeleteRange) | ||||
| 		} | ||||
| 	case *pb.RequestOp_RequestTxn: | ||||
| 		if tv.RequestTxn != nil { | ||||
| 			return TxnRequestToOp(tv.RequestTxn) | ||||
| 		} | ||||
| 	} | ||||
| 	panic("unknown request") | ||||
| } | ||||
|  | ||||
| func RangeRequestToOp(r *pb.RangeRequest) clientv3.Op { | ||||
| 	opts := []clientv3.OpOption{} | ||||
| 	if len(r.RangeEnd) != 0 { | ||||
| 		opts = append(opts, clientv3.WithRange(string(r.RangeEnd))) | ||||
| 	} | ||||
| 	opts = append(opts, clientv3.WithRev(r.Revision)) | ||||
| 	opts = append(opts, clientv3.WithLimit(r.Limit)) | ||||
| 	opts = append(opts, clientv3.WithSort( | ||||
| 		clientv3.SortTarget(r.SortTarget), | ||||
| 		clientv3.SortOrder(r.SortOrder)), | ||||
| 	) | ||||
| 	opts = append(opts, clientv3.WithMaxCreateRev(r.MaxCreateRevision)) | ||||
| 	opts = append(opts, clientv3.WithMinCreateRev(r.MinCreateRevision)) | ||||
| 	opts = append(opts, clientv3.WithMaxModRev(r.MaxModRevision)) | ||||
| 	opts = append(opts, clientv3.WithMinModRev(r.MinModRevision)) | ||||
| 	if r.CountOnly { | ||||
| 		opts = append(opts, clientv3.WithCountOnly()) | ||||
| 	} | ||||
| 	if r.KeysOnly { | ||||
| 		opts = append(opts, clientv3.WithKeysOnly()) | ||||
| 	} | ||||
| 	if r.Serializable { | ||||
| 		opts = append(opts, clientv3.WithSerializable()) | ||||
| 	} | ||||
|  | ||||
| 	return clientv3.OpGet(string(r.Key), opts...) | ||||
| } | ||||
|  | ||||
| func PutRequestToOp(r *pb.PutRequest) clientv3.Op { | ||||
| 	opts := []clientv3.OpOption{} | ||||
| 	opts = append(opts, clientv3.WithLease(clientv3.LeaseID(r.Lease))) | ||||
| 	if r.IgnoreValue { | ||||
| 		opts = append(opts, clientv3.WithIgnoreValue()) | ||||
| 	} | ||||
| 	if r.IgnoreLease { | ||||
| 		opts = append(opts, clientv3.WithIgnoreLease()) | ||||
| 	} | ||||
| 	if r.PrevKv { | ||||
| 		opts = append(opts, clientv3.WithPrevKV()) | ||||
| 	} | ||||
| 	return clientv3.OpPut(string(r.Key), string(r.Value), opts...) | ||||
| } | ||||
|  | ||||
| func DelRequestToOp(r *pb.DeleteRangeRequest) clientv3.Op { | ||||
| 	opts := []clientv3.OpOption{} | ||||
| 	if len(r.RangeEnd) != 0 { | ||||
| 		opts = append(opts, clientv3.WithRange(string(r.RangeEnd))) | ||||
| 	} | ||||
| 	if r.PrevKv { | ||||
| 		opts = append(opts, clientv3.WithPrevKV()) | ||||
| 	} | ||||
| 	return clientv3.OpDelete(string(r.Key), opts...) | ||||
| } | ||||
|  | ||||
| func TxnRequestToOp(r *pb.TxnRequest) clientv3.Op { | ||||
| 	cmps := make([]clientv3.Cmp, len(r.Compare)) | ||||
| 	thenops := make([]clientv3.Op, len(r.Success)) | ||||
| 	elseops := make([]clientv3.Op, len(r.Failure)) | ||||
| 	for i := range r.Compare { | ||||
| 		cmps[i] = (clientv3.Cmp)(*r.Compare[i]) | ||||
| 	} | ||||
| 	for i := range r.Success { | ||||
| 		thenops[i] = requestOpToOp(r.Success[i]) | ||||
| 	} | ||||
| 	for i := range r.Failure { | ||||
| 		elseops[i] = requestOpToOp(r.Failure[i]) | ||||
| 	} | ||||
| 	return clientv3.OpTxn(cmps, thenops, elseops) | ||||
| } | ||||
							
								
								
									
										113
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/leader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										113
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/leader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,113 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"math" | ||||
| 	"sync" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
|  | ||||
| 	"golang.org/x/time/rate" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	lostLeaderKey  = "__lostleader" // watched to detect leader loss | ||||
| 	retryPerSecond = 10 | ||||
| ) | ||||
|  | ||||
| type leader struct { | ||||
| 	ctx context.Context | ||||
| 	w   clientv3.Watcher | ||||
| 	// mu protects leaderc updates. | ||||
| 	mu       sync.RWMutex | ||||
| 	leaderc  chan struct{} | ||||
| 	disconnc chan struct{} | ||||
| 	donec    chan struct{} | ||||
| } | ||||
|  | ||||
| func newLeader(ctx context.Context, w clientv3.Watcher) *leader { | ||||
| 	l := &leader{ | ||||
| 		ctx:      clientv3.WithRequireLeader(ctx), | ||||
| 		w:        w, | ||||
| 		leaderc:  make(chan struct{}), | ||||
| 		disconnc: make(chan struct{}), | ||||
| 		donec:    make(chan struct{}), | ||||
| 	} | ||||
| 	// begin assuming leader is lost | ||||
| 	close(l.leaderc) | ||||
| 	go l.recvLoop() | ||||
| 	return l | ||||
| } | ||||
|  | ||||
| func (l *leader) recvLoop() { | ||||
| 	defer close(l.donec) | ||||
|  | ||||
| 	limiter := rate.NewLimiter(rate.Limit(retryPerSecond), retryPerSecond) | ||||
| 	rev := int64(math.MaxInt64 - 2) | ||||
| 	for limiter.Wait(l.ctx) == nil { | ||||
| 		wch := l.w.Watch(l.ctx, lostLeaderKey, clientv3.WithRev(rev), clientv3.WithCreatedNotify()) | ||||
| 		cresp, ok := <-wch | ||||
| 		if !ok { | ||||
| 			l.loseLeader() | ||||
| 			continue | ||||
| 		} | ||||
| 		if cresp.Err() != nil { | ||||
| 			l.loseLeader() | ||||
| 			if clientv3.IsConnCanceled(cresp.Err()) { | ||||
| 				close(l.disconnc) | ||||
| 				return | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		l.gotLeader() | ||||
| 		<-wch | ||||
| 		l.loseLeader() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *leader) loseLeader() { | ||||
| 	l.mu.RLock() | ||||
| 	defer l.mu.RUnlock() | ||||
| 	select { | ||||
| 	case <-l.leaderc: | ||||
| 	default: | ||||
| 		close(l.leaderc) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // gotLeader will force update the leadership status to having a leader. | ||||
| func (l *leader) gotLeader() { | ||||
| 	l.mu.Lock() | ||||
| 	defer l.mu.Unlock() | ||||
| 	select { | ||||
| 	case <-l.leaderc: | ||||
| 		l.leaderc = make(chan struct{}) | ||||
| 	default: | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (l *leader) disconnectNotify() <-chan struct{} { return l.disconnc } | ||||
|  | ||||
| func (l *leader) stopNotify() <-chan struct{} { return l.donec } | ||||
|  | ||||
| // lostNotify returns a channel that is closed if there has been | ||||
| // a leader loss not yet followed by a leader reacquire. | ||||
| func (l *leader) lostNotify() <-chan struct{} { | ||||
| 	l.mu.RLock() | ||||
| 	defer l.mu.RUnlock() | ||||
| 	return l.leaderc | ||||
| } | ||||
							
								
								
									
										384
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lease.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										384
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lease.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,384 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| 	"sync/atomic" | ||||
| 	"time" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/api/v3/v3rpc/rpctypes" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
|  | ||||
| 	"google.golang.org/grpc" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/metadata" | ||||
| 	"google.golang.org/grpc/status" | ||||
| ) | ||||
|  | ||||
| type leaseProxy struct { | ||||
| 	// leaseClient handles req from LeaseGrant() that requires a lease ID. | ||||
| 	leaseClient pb.LeaseClient | ||||
|  | ||||
| 	lessor clientv3.Lease | ||||
|  | ||||
| 	ctx context.Context | ||||
|  | ||||
| 	leader *leader | ||||
|  | ||||
| 	// mu protects adding outstanding leaseProxyStream through wg. | ||||
| 	mu sync.RWMutex | ||||
|  | ||||
| 	// wg waits until all outstanding leaseProxyStream quit. | ||||
| 	wg sync.WaitGroup | ||||
| } | ||||
|  | ||||
| func NewLeaseProxy(ctx context.Context, c *clientv3.Client) (pb.LeaseServer, <-chan struct{}) { | ||||
| 	cctx, cancel := context.WithCancel(ctx) | ||||
| 	lp := &leaseProxy{ | ||||
| 		leaseClient: pb.NewLeaseClient(c.ActiveConnection()), | ||||
| 		lessor:      c.Lease, | ||||
| 		ctx:         cctx, | ||||
| 		leader:      newLeader(cctx, c.Watcher), | ||||
| 	} | ||||
| 	ch := make(chan struct{}) | ||||
| 	go func() { | ||||
| 		defer close(ch) | ||||
| 		<-lp.leader.stopNotify() | ||||
| 		lp.mu.Lock() | ||||
| 		select { | ||||
| 		case <-lp.ctx.Done(): | ||||
| 		case <-lp.leader.disconnectNotify(): | ||||
| 			cancel() | ||||
| 		} | ||||
| 		<-lp.ctx.Done() | ||||
| 		lp.mu.Unlock() | ||||
| 		lp.wg.Wait() | ||||
| 	}() | ||||
| 	return lp, ch | ||||
| } | ||||
|  | ||||
| func (lp *leaseProxy) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { | ||||
| 	rp, err := lp.leaseClient.LeaseGrant(ctx, cr, grpc.WaitForReady(true)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	lp.leader.gotLeader() | ||||
| 	return rp, nil | ||||
| } | ||||
|  | ||||
| func (lp *leaseProxy) LeaseRevoke(ctx context.Context, rr *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) { | ||||
| 	r, err := lp.lessor.Revoke(ctx, clientv3.LeaseID(rr.ID)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	lp.leader.gotLeader() | ||||
| 	return (*pb.LeaseRevokeResponse)(r), nil | ||||
| } | ||||
|  | ||||
| func (lp *leaseProxy) LeaseTimeToLive(ctx context.Context, rr *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) { | ||||
| 	var ( | ||||
| 		r   *clientv3.LeaseTimeToLiveResponse | ||||
| 		err error | ||||
| 	) | ||||
| 	if rr.Keys { | ||||
| 		r, err = lp.lessor.TimeToLive(ctx, clientv3.LeaseID(rr.ID), clientv3.WithAttachedKeys()) | ||||
| 	} else { | ||||
| 		r, err = lp.lessor.TimeToLive(ctx, clientv3.LeaseID(rr.ID)) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	rp := &pb.LeaseTimeToLiveResponse{ | ||||
| 		Header:     r.ResponseHeader, | ||||
| 		ID:         int64(r.ID), | ||||
| 		TTL:        r.TTL, | ||||
| 		GrantedTTL: r.GrantedTTL, | ||||
| 		Keys:       r.Keys, | ||||
| 	} | ||||
| 	return rp, err | ||||
| } | ||||
|  | ||||
| func (lp *leaseProxy) LeaseLeases(ctx context.Context, rr *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error) { | ||||
| 	r, err := lp.lessor.Leases(ctx) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	leases := make([]*pb.LeaseStatus, len(r.Leases)) | ||||
| 	for i := range r.Leases { | ||||
| 		leases[i] = &pb.LeaseStatus{ID: int64(r.Leases[i].ID)} | ||||
| 	} | ||||
| 	rp := &pb.LeaseLeasesResponse{ | ||||
| 		Header: r.ResponseHeader, | ||||
| 		Leases: leases, | ||||
| 	} | ||||
| 	return rp, err | ||||
| } | ||||
|  | ||||
| func (lp *leaseProxy) LeaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) error { | ||||
| 	lp.mu.Lock() | ||||
| 	select { | ||||
| 	case <-lp.ctx.Done(): | ||||
| 		lp.mu.Unlock() | ||||
| 		return lp.ctx.Err() | ||||
| 	default: | ||||
| 		lp.wg.Add(1) | ||||
| 	} | ||||
| 	lp.mu.Unlock() | ||||
|  | ||||
| 	ctx, cancel := context.WithCancel(stream.Context()) | ||||
| 	lps := leaseProxyStream{ | ||||
| 		stream:          stream, | ||||
| 		lessor:          lp.lessor, | ||||
| 		keepAliveLeases: make(map[int64]*atomicCounter), | ||||
| 		respc:           make(chan *pb.LeaseKeepAliveResponse), | ||||
| 		ctx:             ctx, | ||||
| 		cancel:          cancel, | ||||
| 	} | ||||
|  | ||||
| 	errc := make(chan error, 2) | ||||
|  | ||||
| 	var lostLeaderC <-chan struct{} | ||||
| 	if md, ok := metadata.FromOutgoingContext(stream.Context()); ok { | ||||
| 		v := md[rpctypes.MetadataRequireLeaderKey] | ||||
| 		if len(v) > 0 && v[0] == rpctypes.MetadataHasLeader { | ||||
| 			lostLeaderC = lp.leader.lostNotify() | ||||
| 			// if leader is known to be lost at creation time, avoid | ||||
| 			// letting events through at all | ||||
| 			select { | ||||
| 			case <-lostLeaderC: | ||||
| 				lp.wg.Done() | ||||
| 				return rpctypes.ErrNoLeader | ||||
| 			default: | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	stopc := make(chan struct{}, 3) | ||||
| 	go func() { | ||||
| 		defer func() { stopc <- struct{}{} }() | ||||
| 		if err := lps.recvLoop(); err != nil { | ||||
| 			errc <- err | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	go func() { | ||||
| 		defer func() { stopc <- struct{}{} }() | ||||
| 		if err := lps.sendLoop(); err != nil { | ||||
| 			errc <- err | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	// tears down LeaseKeepAlive stream if leader goes down or entire leaseProxy is terminated. | ||||
| 	go func() { | ||||
| 		defer func() { stopc <- struct{}{} }() | ||||
| 		select { | ||||
| 		case <-lostLeaderC: | ||||
| 		case <-ctx.Done(): | ||||
| 		case <-lp.ctx.Done(): | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	var err error | ||||
| 	select { | ||||
| 	case <-stopc: | ||||
| 		stopc <- struct{}{} | ||||
| 	case err = <-errc: | ||||
| 	} | ||||
| 	cancel() | ||||
|  | ||||
| 	// recv/send may only shutdown after function exits; | ||||
| 	// this goroutine notifies lease proxy that the stream is through | ||||
| 	go func() { | ||||
| 		<-stopc | ||||
| 		<-stopc | ||||
| 		<-stopc | ||||
| 		lps.close() | ||||
| 		close(errc) | ||||
| 		lp.wg.Done() | ||||
| 	}() | ||||
|  | ||||
| 	select { | ||||
| 	case <-lostLeaderC: | ||||
| 		return rpctypes.ErrNoLeader | ||||
| 	case <-lp.leader.disconnectNotify(): | ||||
| 		return status.Error(codes.Canceled, "the client connection is closing") | ||||
| 	default: | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		return ctx.Err() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type leaseProxyStream struct { | ||||
| 	stream pb.Lease_LeaseKeepAliveServer | ||||
|  | ||||
| 	lessor clientv3.Lease | ||||
| 	// wg tracks keepAliveLoop goroutines | ||||
| 	wg sync.WaitGroup | ||||
| 	// mu protects keepAliveLeases | ||||
| 	mu sync.RWMutex | ||||
| 	// keepAliveLeases tracks how many outstanding keepalive requests which need responses are on a lease. | ||||
| 	keepAliveLeases map[int64]*atomicCounter | ||||
| 	// respc receives lease keepalive responses from etcd backend | ||||
| 	respc chan *pb.LeaseKeepAliveResponse | ||||
|  | ||||
| 	ctx    context.Context | ||||
| 	cancel context.CancelFunc | ||||
| } | ||||
|  | ||||
| func (lps *leaseProxyStream) recvLoop() error { | ||||
| 	for { | ||||
| 		rr, err := lps.stream.Recv() | ||||
| 		if err == io.EOF { | ||||
| 			return nil | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		lps.mu.Lock() | ||||
| 		neededResps, ok := lps.keepAliveLeases[rr.ID] | ||||
| 		if !ok { | ||||
| 			neededResps = &atomicCounter{} | ||||
| 			lps.keepAliveLeases[rr.ID] = neededResps | ||||
| 			lps.wg.Add(1) | ||||
| 			go func() { | ||||
| 				defer lps.wg.Done() | ||||
| 				if err := lps.keepAliveLoop(rr.ID, neededResps); err != nil { | ||||
| 					lps.cancel() | ||||
| 				} | ||||
| 			}() | ||||
| 		} | ||||
| 		neededResps.add(1) | ||||
| 		lps.mu.Unlock() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (lps *leaseProxyStream) keepAliveLoop(leaseID int64, neededResps *atomicCounter) error { | ||||
| 	cctx, ccancel := context.WithCancel(lps.ctx) | ||||
| 	defer ccancel() | ||||
| 	respc, err := lps.lessor.KeepAlive(cctx, clientv3.LeaseID(leaseID)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// ticker expires when loop hasn't received keepalive within TTL | ||||
| 	var ticker <-chan time.Time | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-ticker: | ||||
| 			lps.mu.Lock() | ||||
| 			// if there are outstanding keepAlive reqs at the moment of ticker firing, | ||||
| 			// don't close keepAliveLoop(), let it continuing to process the KeepAlive reqs. | ||||
| 			if neededResps.get() > 0 { | ||||
| 				lps.mu.Unlock() | ||||
| 				ticker = nil | ||||
| 				continue | ||||
| 			} | ||||
| 			delete(lps.keepAliveLeases, leaseID) | ||||
| 			lps.mu.Unlock() | ||||
| 			return nil | ||||
| 		case rp, ok := <-respc: | ||||
| 			if !ok { | ||||
| 				lps.mu.Lock() | ||||
| 				delete(lps.keepAliveLeases, leaseID) | ||||
| 				lps.mu.Unlock() | ||||
| 				if neededResps.get() == 0 { | ||||
| 					return nil | ||||
| 				} | ||||
| 				ttlResp, err := lps.lessor.TimeToLive(cctx, clientv3.LeaseID(leaseID)) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				r := &pb.LeaseKeepAliveResponse{ | ||||
| 					Header: ttlResp.ResponseHeader, | ||||
| 					ID:     int64(ttlResp.ID), | ||||
| 					TTL:    ttlResp.TTL, | ||||
| 				} | ||||
| 				for neededResps.get() > 0 { | ||||
| 					select { | ||||
| 					case lps.respc <- r: | ||||
| 						neededResps.add(-1) | ||||
| 					case <-lps.ctx.Done(): | ||||
| 						return nil | ||||
| 					} | ||||
| 				} | ||||
| 				return nil | ||||
| 			} | ||||
| 			if neededResps.get() == 0 { | ||||
| 				continue | ||||
| 			} | ||||
| 			ticker = time.After(time.Duration(rp.TTL) * time.Second) | ||||
| 			r := &pb.LeaseKeepAliveResponse{ | ||||
| 				Header: rp.ResponseHeader, | ||||
| 				ID:     int64(rp.ID), | ||||
| 				TTL:    rp.TTL, | ||||
| 			} | ||||
| 			lps.replyToClient(r, neededResps) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (lps *leaseProxyStream) replyToClient(r *pb.LeaseKeepAliveResponse, neededResps *atomicCounter) { | ||||
| 	timer := time.After(500 * time.Millisecond) | ||||
| 	for neededResps.get() > 0 { | ||||
| 		select { | ||||
| 		case lps.respc <- r: | ||||
| 			neededResps.add(-1) | ||||
| 		case <-timer: | ||||
| 			return | ||||
| 		case <-lps.ctx.Done(): | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (lps *leaseProxyStream) sendLoop() error { | ||||
| 	for { | ||||
| 		select { | ||||
| 		case lrp, ok := <-lps.respc: | ||||
| 			if !ok { | ||||
| 				return nil | ||||
| 			} | ||||
| 			if err := lps.stream.Send(lrp); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		case <-lps.ctx.Done(): | ||||
| 			return lps.ctx.Err() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (lps *leaseProxyStream) close() { | ||||
| 	lps.cancel() | ||||
| 	lps.wg.Wait() | ||||
| 	// only close respc channel if all the keepAliveLoop() goroutines have finished | ||||
| 	// this ensures those goroutines don't send resp to a closed resp channel | ||||
| 	close(lps.respc) | ||||
| } | ||||
|  | ||||
| type atomicCounter struct { | ||||
| 	counter int64 | ||||
| } | ||||
|  | ||||
| func (ac *atomicCounter) add(delta int64) { | ||||
| 	atomic.AddInt64(&ac.counter, delta) | ||||
| } | ||||
|  | ||||
| func (ac *atomicCounter) get() int64 { | ||||
| 	return atomic.LoadInt64(&ac.counter) | ||||
| } | ||||
							
								
								
									
										38
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,38 +0,0 @@ | ||||
| // Copyright 2017 The etcd Lockors | ||||
| // | ||||
| // 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb" | ||||
| ) | ||||
|  | ||||
| type lockProxy struct { | ||||
| 	client *clientv3.Client | ||||
| } | ||||
|  | ||||
| func NewLockProxy(client *clientv3.Client) v3lockpb.LockServer { | ||||
| 	return &lockProxy{client: client} | ||||
| } | ||||
|  | ||||
| func (lp *lockProxy) Lock(ctx context.Context, req *v3lockpb.LockRequest) (*v3lockpb.LockResponse, error) { | ||||
| 	return v3lockpb.NewLockClient(lp.client.ActiveConnection()).Lock(ctx, req) | ||||
| } | ||||
|  | ||||
| func (lp *lockProxy) Unlock(ctx context.Context, req *v3lockpb.UnlockRequest) (*v3lockpb.UnlockResponse, error) { | ||||
| 	return v3lockpb.NewLockClient(lp.client.ActiveConnection()).Unlock(ctx, req) | ||||
| } | ||||
							
								
								
									
										95
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/maintenance.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										95
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/maintenance.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,95 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| ) | ||||
|  | ||||
| type maintenanceProxy struct { | ||||
| 	client *clientv3.Client | ||||
| } | ||||
|  | ||||
| func NewMaintenanceProxy(c *clientv3.Client) pb.MaintenanceServer { | ||||
| 	return &maintenanceProxy{ | ||||
| 		client: c, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (mp *maintenanceProxy) Defragment(ctx context.Context, dr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) { | ||||
| 	conn := mp.client.ActiveConnection() | ||||
| 	return pb.NewMaintenanceClient(conn).Defragment(ctx, dr) | ||||
| } | ||||
|  | ||||
| func (mp *maintenanceProxy) Snapshot(sr *pb.SnapshotRequest, stream pb.Maintenance_SnapshotServer) error { | ||||
| 	conn := mp.client.ActiveConnection() | ||||
| 	ctx, cancel := context.WithCancel(stream.Context()) | ||||
| 	defer cancel() | ||||
|  | ||||
| 	ctx = withClientAuthToken(ctx, stream.Context()) | ||||
|  | ||||
| 	sc, err := pb.NewMaintenanceClient(conn).Snapshot(ctx, sr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for { | ||||
| 		rr, err := sc.Recv() | ||||
| 		if err != nil { | ||||
| 			if err == io.EOF { | ||||
| 				return nil | ||||
| 			} | ||||
| 			return err | ||||
| 		} | ||||
| 		err = stream.Send(rr) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (mp *maintenanceProxy) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) { | ||||
| 	conn := mp.client.ActiveConnection() | ||||
| 	return pb.NewMaintenanceClient(conn).Hash(ctx, r) | ||||
| } | ||||
|  | ||||
| func (mp *maintenanceProxy) HashKV(ctx context.Context, r *pb.HashKVRequest) (*pb.HashKVResponse, error) { | ||||
| 	conn := mp.client.ActiveConnection() | ||||
| 	return pb.NewMaintenanceClient(conn).HashKV(ctx, r) | ||||
| } | ||||
|  | ||||
| func (mp *maintenanceProxy) Alarm(ctx context.Context, r *pb.AlarmRequest) (*pb.AlarmResponse, error) { | ||||
| 	conn := mp.client.ActiveConnection() | ||||
| 	return pb.NewMaintenanceClient(conn).Alarm(ctx, r) | ||||
| } | ||||
|  | ||||
| func (mp *maintenanceProxy) Status(ctx context.Context, r *pb.StatusRequest) (*pb.StatusResponse, error) { | ||||
| 	conn := mp.client.ActiveConnection() | ||||
| 	return pb.NewMaintenanceClient(conn).Status(ctx, r) | ||||
| } | ||||
|  | ||||
| func (mp *maintenanceProxy) MoveLeader(ctx context.Context, r *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) { | ||||
| 	conn := mp.client.ActiveConnection() | ||||
| 	return pb.NewMaintenanceClient(conn).MoveLeader(ctx, r) | ||||
| } | ||||
|  | ||||
| func (mp *maintenanceProxy) Downgrade(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) { | ||||
| 	conn := mp.client.ActiveConnection() | ||||
| 	return pb.NewMaintenanceClient(conn).Downgrade(ctx, r) | ||||
| } | ||||
							
								
								
									
										121
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/metrics.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										121
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/metrics.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,121 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"math/rand" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/prometheus/client_golang/prometheus" | ||||
| 	"github.com/prometheus/client_golang/prometheus/promhttp" | ||||
| 	"go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	watchersCoalescing = prometheus.NewGauge(prometheus.GaugeOpts{ | ||||
| 		Namespace: "etcd", | ||||
| 		Subsystem: "grpc_proxy", | ||||
| 		Name:      "watchers_coalescing_total", | ||||
| 		Help:      "Total number of current watchers coalescing", | ||||
| 	}) | ||||
| 	eventsCoalescing = prometheus.NewCounter(prometheus.CounterOpts{ | ||||
| 		Namespace: "etcd", | ||||
| 		Subsystem: "grpc_proxy", | ||||
| 		Name:      "events_coalescing_total", | ||||
| 		Help:      "Total number of events coalescing", | ||||
| 	}) | ||||
| 	cacheKeys = prometheus.NewGauge(prometheus.GaugeOpts{ | ||||
| 		Namespace: "etcd", | ||||
| 		Subsystem: "grpc_proxy", | ||||
| 		Name:      "cache_keys_total", | ||||
| 		Help:      "Total number of keys/ranges cached", | ||||
| 	}) | ||||
| 	cacheHits = prometheus.NewGauge(prometheus.GaugeOpts{ | ||||
| 		Namespace: "etcd", | ||||
| 		Subsystem: "grpc_proxy", | ||||
| 		Name:      "cache_hits_total", | ||||
| 		Help:      "Total number of cache hits", | ||||
| 	}) | ||||
| 	cachedMisses = prometheus.NewGauge(prometheus.GaugeOpts{ | ||||
| 		Namespace: "etcd", | ||||
| 		Subsystem: "grpc_proxy", | ||||
| 		Name:      "cache_misses_total", | ||||
| 		Help:      "Total number of cache misses", | ||||
| 	}) | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	prometheus.MustRegister(watchersCoalescing) | ||||
| 	prometheus.MustRegister(eventsCoalescing) | ||||
| 	prometheus.MustRegister(cacheKeys) | ||||
| 	prometheus.MustRegister(cacheHits) | ||||
| 	prometheus.MustRegister(cachedMisses) | ||||
| } | ||||
|  | ||||
| // HandleMetrics performs a GET request against etcd endpoint and returns '/metrics'. | ||||
| func HandleMetrics(mux *http.ServeMux, c *http.Client, eps []string) { | ||||
| 	// random shuffle endpoints | ||||
| 	r := rand.New(rand.NewSource(int64(time.Now().Nanosecond()))) | ||||
| 	if len(eps) > 1 { | ||||
| 		eps = shuffleEndpoints(r, eps) | ||||
| 	} | ||||
|  | ||||
| 	pathMetrics := etcdhttp.PathMetrics | ||||
| 	mux.HandleFunc(pathMetrics, func(w http.ResponseWriter, r *http.Request) { | ||||
| 		target := fmt.Sprintf("%s%s", eps[0], pathMetrics) | ||||
| 		if !strings.HasPrefix(target, "http") { | ||||
| 			scheme := "http" | ||||
| 			if r.TLS != nil { | ||||
| 				scheme = "https" | ||||
| 			} | ||||
| 			target = fmt.Sprintf("%s://%s", scheme, target) | ||||
| 		} | ||||
|  | ||||
| 		resp, err := c.Get(target) | ||||
| 		if err != nil { | ||||
| 			http.Error(w, "Internal server error", http.StatusInternalServerError) | ||||
| 			return | ||||
| 		} | ||||
| 		defer resp.Body.Close() | ||||
| 		w.Header().Set("Content-Type", "text/plain; version=0.0.4") | ||||
| 		body, _ := ioutil.ReadAll(resp.Body) | ||||
| 		fmt.Fprintf(w, "%s", body) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // HandleProxyMetrics registers metrics handler on '/proxy/metrics'. | ||||
| func HandleProxyMetrics(mux *http.ServeMux) { | ||||
| 	mux.Handle(etcdhttp.PathProxyMetrics, promhttp.Handler()) | ||||
| } | ||||
|  | ||||
| func shuffleEndpoints(r *rand.Rand, eps []string) []string { | ||||
| 	// copied from Go 1.9<= rand.Rand.Perm | ||||
| 	n := len(eps) | ||||
| 	p := make([]int, n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		j := r.Intn(i + 1) | ||||
| 		p[i] = p[j] | ||||
| 		p[j] = i | ||||
| 	} | ||||
| 	neps := make([]string, n) | ||||
| 	for i, k := range p { | ||||
| 		neps[i] = eps[k] | ||||
| 	} | ||||
| 	return neps | ||||
| } | ||||
							
								
								
									
										102
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/register.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										102
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/register.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,102 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"os" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/client/v3/concurrency" | ||||
| 	"go.etcd.io/etcd/client/v3/naming/endpoints" | ||||
|  | ||||
| 	"go.uber.org/zap" | ||||
| 	"golang.org/x/time/rate" | ||||
| ) | ||||
|  | ||||
| // allow maximum 1 retry per second | ||||
| const registerRetryRate = 1 | ||||
|  | ||||
| // Register registers itself as a grpc-proxy server by writing prefixed-key | ||||
| // with session of specified TTL (in seconds). The returned channel is closed | ||||
| // when the client's context is canceled. | ||||
| func Register(lg *zap.Logger, c *clientv3.Client, prefix string, addr string, ttl int) <-chan struct{} { | ||||
| 	rm := rate.NewLimiter(rate.Limit(registerRetryRate), registerRetryRate) | ||||
|  | ||||
| 	donec := make(chan struct{}) | ||||
| 	go func() { | ||||
| 		defer close(donec) | ||||
|  | ||||
| 		for rm.Wait(c.Ctx()) == nil { | ||||
| 			ss, err := registerSession(lg, c, prefix, addr, ttl) | ||||
| 			if err != nil { | ||||
| 				lg.Warn("failed to create a session", zap.Error(err)) | ||||
| 				continue | ||||
| 			} | ||||
| 			select { | ||||
| 			case <-c.Ctx().Done(): | ||||
| 				ss.Close() | ||||
| 				return | ||||
|  | ||||
| 			case <-ss.Done(): | ||||
| 				lg.Warn("session expired; possible network partition or server restart") | ||||
| 				lg.Warn("creating a new session to rejoin") | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	return donec | ||||
| } | ||||
|  | ||||
| func registerSession(lg *zap.Logger, c *clientv3.Client, prefix string, addr string, ttl int) (*concurrency.Session, error) { | ||||
| 	ss, err := concurrency.NewSession(c, concurrency.WithTTL(ttl)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	em, err := endpoints.NewManager(c, prefix) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	endpoint := endpoints.Endpoint{Addr: addr, Metadata: getMeta()} | ||||
| 	if err = em.AddEndpoint(c.Ctx(), prefix+"/"+addr, endpoint, clientv3.WithLease(ss.Lease())); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	lg.Info( | ||||
| 		"registered session with lease", | ||||
| 		zap.String("addr", addr), | ||||
| 		zap.Int("lease-ttl", ttl), | ||||
| 	) | ||||
| 	return ss, nil | ||||
| } | ||||
|  | ||||
| // meta represents metadata of proxy register. | ||||
| type meta struct { | ||||
| 	Name string `json:"name"` | ||||
| } | ||||
|  | ||||
| func getMeta() string { | ||||
| 	hostname, _ := os.Hostname() | ||||
| 	bts, _ := json.Marshal(meta{Name: hostname}) | ||||
| 	return string(bts) | ||||
| } | ||||
|  | ||||
| func decodeMeta(s string) (meta, error) { | ||||
| 	m := meta{} | ||||
| 	err := json.Unmarshal([]byte(s), &m) | ||||
| 	return m, err | ||||
| } | ||||
							
								
								
									
										75
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										75
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,75 +0,0 @@ | ||||
| // Copyright 2017 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"go.etcd.io/etcd/api/v3/v3rpc/rpctypes" | ||||
|  | ||||
| 	"google.golang.org/grpc" | ||||
| 	"google.golang.org/grpc/metadata" | ||||
| ) | ||||
|  | ||||
| func getAuthTokenFromClient(ctx context.Context) string { | ||||
| 	md, ok := metadata.FromIncomingContext(ctx) | ||||
| 	if ok { | ||||
| 		ts, ok := md[rpctypes.TokenFieldNameGRPC] | ||||
| 		if ok { | ||||
| 			return ts[0] | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func withClientAuthToken(ctx, ctxWithToken context.Context) context.Context { | ||||
| 	token := getAuthTokenFromClient(ctxWithToken) | ||||
| 	if token != "" { | ||||
| 		ctx = context.WithValue(ctx, rpctypes.TokenFieldNameGRPC, token) | ||||
| 	} | ||||
| 	return ctx | ||||
| } | ||||
|  | ||||
| type proxyTokenCredential struct { | ||||
| 	token string | ||||
| } | ||||
|  | ||||
| func (cred *proxyTokenCredential) RequireTransportSecurity() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (cred *proxyTokenCredential) GetRequestMetadata(ctx context.Context, s ...string) (map[string]string, error) { | ||||
| 	return map[string]string{ | ||||
| 		rpctypes.TokenFieldNameGRPC: cred.token, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func AuthUnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { | ||||
| 	token := getAuthTokenFromClient(ctx) | ||||
| 	if token != "" { | ||||
| 		tokenCred := &proxyTokenCredential{token} | ||||
| 		opts = append(opts, grpc.PerRPCCredentials(tokenCred)) | ||||
| 	} | ||||
| 	return invoker(ctx, method, req, reply, cc, opts...) | ||||
| } | ||||
|  | ||||
| func AuthStreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { | ||||
| 	tokenif := ctx.Value(rpctypes.TokenFieldNameGRPC) | ||||
| 	if tokenif != nil { | ||||
| 		tokenCred := &proxyTokenCredential{tokenif.(string)} | ||||
| 		opts = append(opts, grpc.PerRPCCredentials(tokenCred)) | ||||
| 	} | ||||
| 	return streamer(ctx, desc, cc, method, opts...) | ||||
| } | ||||
							
								
								
									
										313
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										313
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,313 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/api/v3/v3rpc/rpctypes" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc" | ||||
|  | ||||
| 	"go.uber.org/zap" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/metadata" | ||||
| 	"google.golang.org/grpc/status" | ||||
| ) | ||||
|  | ||||
| type watchProxy struct { | ||||
| 	cw  clientv3.Watcher | ||||
| 	ctx context.Context | ||||
|  | ||||
| 	leader *leader | ||||
|  | ||||
| 	ranges *watchRanges | ||||
|  | ||||
| 	// mu protects adding outstanding watch servers through wg. | ||||
| 	mu sync.Mutex | ||||
|  | ||||
| 	// wg waits until all outstanding watch servers quit. | ||||
| 	wg sync.WaitGroup | ||||
|  | ||||
| 	// kv is used for permission checking | ||||
| 	kv clientv3.KV | ||||
| 	lg *zap.Logger | ||||
| } | ||||
|  | ||||
| func NewWatchProxy(ctx context.Context, lg *zap.Logger, c *clientv3.Client) (pb.WatchServer, <-chan struct{}) { | ||||
| 	cctx, cancel := context.WithCancel(ctx) | ||||
| 	wp := &watchProxy{ | ||||
| 		cw:     c.Watcher, | ||||
| 		ctx:    cctx, | ||||
| 		leader: newLeader(cctx, c.Watcher), | ||||
|  | ||||
| 		kv: c.KV, // for permission checking | ||||
| 		lg: lg, | ||||
| 	} | ||||
| 	wp.ranges = newWatchRanges(wp) | ||||
| 	ch := make(chan struct{}) | ||||
| 	go func() { | ||||
| 		defer close(ch) | ||||
| 		<-wp.leader.stopNotify() | ||||
| 		wp.mu.Lock() | ||||
| 		select { | ||||
| 		case <-wp.ctx.Done(): | ||||
| 		case <-wp.leader.disconnectNotify(): | ||||
| 			cancel() | ||||
| 		} | ||||
| 		<-wp.ctx.Done() | ||||
| 		wp.mu.Unlock() | ||||
| 		wp.wg.Wait() | ||||
| 		wp.ranges.stop() | ||||
| 	}() | ||||
| 	return wp, ch | ||||
| } | ||||
|  | ||||
| func (wp *watchProxy) Watch(stream pb.Watch_WatchServer) (err error) { | ||||
| 	wp.mu.Lock() | ||||
| 	select { | ||||
| 	case <-wp.ctx.Done(): | ||||
| 		wp.mu.Unlock() | ||||
| 		select { | ||||
| 		case <-wp.leader.disconnectNotify(): | ||||
| 			return status.Error(codes.Canceled, "the client connection is closing") | ||||
| 		default: | ||||
| 			return wp.ctx.Err() | ||||
| 		} | ||||
| 	default: | ||||
| 		wp.wg.Add(1) | ||||
| 	} | ||||
| 	wp.mu.Unlock() | ||||
|  | ||||
| 	ctx, cancel := context.WithCancel(stream.Context()) | ||||
| 	wps := &watchProxyStream{ | ||||
| 		ranges:   wp.ranges, | ||||
| 		watchers: make(map[int64]*watcher), | ||||
| 		stream:   stream, | ||||
| 		watchCh:  make(chan *pb.WatchResponse, 1024), | ||||
| 		ctx:      ctx, | ||||
| 		cancel:   cancel, | ||||
| 		kv:       wp.kv, | ||||
| 		lg:       wp.lg, | ||||
| 	} | ||||
|  | ||||
| 	var lostLeaderC <-chan struct{} | ||||
| 	if md, ok := metadata.FromOutgoingContext(stream.Context()); ok { | ||||
| 		v := md[rpctypes.MetadataRequireLeaderKey] | ||||
| 		if len(v) > 0 && v[0] == rpctypes.MetadataHasLeader { | ||||
| 			lostLeaderC = wp.leader.lostNotify() | ||||
| 			// if leader is known to be lost at creation time, avoid | ||||
| 			// letting events through at all | ||||
| 			select { | ||||
| 			case <-lostLeaderC: | ||||
| 				wp.wg.Done() | ||||
| 				return rpctypes.ErrNoLeader | ||||
| 			default: | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// post to stopc => terminate server stream; can't use a waitgroup | ||||
| 	// since all goroutines will only terminate after Watch() exits. | ||||
| 	stopc := make(chan struct{}, 3) | ||||
| 	go func() { | ||||
| 		defer func() { stopc <- struct{}{} }() | ||||
| 		wps.recvLoop() | ||||
| 	}() | ||||
| 	go func() { | ||||
| 		defer func() { stopc <- struct{}{} }() | ||||
| 		wps.sendLoop() | ||||
| 	}() | ||||
| 	// tear down watch if leader goes down or entire watch proxy is terminated | ||||
| 	go func() { | ||||
| 		defer func() { stopc <- struct{}{} }() | ||||
| 		select { | ||||
| 		case <-lostLeaderC: | ||||
| 		case <-ctx.Done(): | ||||
| 		case <-wp.ctx.Done(): | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	<-stopc | ||||
| 	cancel() | ||||
|  | ||||
| 	// recv/send may only shutdown after function exits; | ||||
| 	// goroutine notifies proxy that stream is through | ||||
| 	go func() { | ||||
| 		<-stopc | ||||
| 		<-stopc | ||||
| 		wps.close() | ||||
| 		wp.wg.Done() | ||||
| 	}() | ||||
|  | ||||
| 	select { | ||||
| 	case <-lostLeaderC: | ||||
| 		return rpctypes.ErrNoLeader | ||||
| 	case <-wp.leader.disconnectNotify(): | ||||
| 		return status.Error(codes.Canceled, "the client connection is closing") | ||||
| 	default: | ||||
| 		return wps.ctx.Err() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // watchProxyStream forwards etcd watch events to a proxied client stream. | ||||
| type watchProxyStream struct { | ||||
| 	ranges *watchRanges | ||||
|  | ||||
| 	// mu protects watchers and nextWatcherID | ||||
| 	mu sync.Mutex | ||||
| 	// watchers receive events from watch broadcast. | ||||
| 	watchers map[int64]*watcher | ||||
| 	// nextWatcherID is the id to assign the next watcher on this stream. | ||||
| 	nextWatcherID int64 | ||||
|  | ||||
| 	stream pb.Watch_WatchServer | ||||
|  | ||||
| 	// watchCh receives watch responses from the watchers. | ||||
| 	watchCh chan *pb.WatchResponse | ||||
|  | ||||
| 	ctx    context.Context | ||||
| 	cancel context.CancelFunc | ||||
|  | ||||
| 	// kv is used for permission checking | ||||
| 	kv clientv3.KV | ||||
| 	lg *zap.Logger | ||||
| } | ||||
|  | ||||
| func (wps *watchProxyStream) close() { | ||||
| 	var wg sync.WaitGroup | ||||
| 	wps.cancel() | ||||
| 	wps.mu.Lock() | ||||
| 	wg.Add(len(wps.watchers)) | ||||
| 	for _, wpsw := range wps.watchers { | ||||
| 		go func(w *watcher) { | ||||
| 			wps.ranges.delete(w) | ||||
| 			wg.Done() | ||||
| 		}(wpsw) | ||||
| 	} | ||||
| 	wps.watchers = nil | ||||
| 	wps.mu.Unlock() | ||||
|  | ||||
| 	wg.Wait() | ||||
|  | ||||
| 	close(wps.watchCh) | ||||
| } | ||||
|  | ||||
| func (wps *watchProxyStream) checkPermissionForWatch(key, rangeEnd []byte) error { | ||||
| 	if len(key) == 0 { | ||||
| 		// If the length of the key is 0, we need to obtain full range. | ||||
| 		// look at clientv3.WithPrefix() | ||||
| 		key = []byte{0} | ||||
| 		rangeEnd = []byte{0} | ||||
| 	} | ||||
| 	req := &pb.RangeRequest{ | ||||
| 		Serializable: true, | ||||
| 		Key:          key, | ||||
| 		RangeEnd:     rangeEnd, | ||||
| 		CountOnly:    true, | ||||
| 		Limit:        1, | ||||
| 	} | ||||
| 	_, err := wps.kv.Do(wps.ctx, RangeRequestToOp(req)) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (wps *watchProxyStream) recvLoop() error { | ||||
| 	for { | ||||
| 		req, err := wps.stream.Recv() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		switch uv := req.RequestUnion.(type) { | ||||
| 		case *pb.WatchRequest_CreateRequest: | ||||
| 			cr := uv.CreateRequest | ||||
|  | ||||
| 			if err := wps.checkPermissionForWatch(cr.Key, cr.RangeEnd); err != nil { | ||||
| 				wps.watchCh <- &pb.WatchResponse{ | ||||
| 					Header:       &pb.ResponseHeader{}, | ||||
| 					WatchId:      -1, | ||||
| 					Created:      true, | ||||
| 					Canceled:     true, | ||||
| 					CancelReason: err.Error(), | ||||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			wps.mu.Lock() | ||||
| 			w := &watcher{ | ||||
| 				wr:  watchRange{string(cr.Key), string(cr.RangeEnd)}, | ||||
| 				id:  wps.nextWatcherID, | ||||
| 				wps: wps, | ||||
|  | ||||
| 				nextrev:  cr.StartRevision, | ||||
| 				progress: cr.ProgressNotify, | ||||
| 				prevKV:   cr.PrevKv, | ||||
| 				filters:  v3rpc.FiltersFromRequest(cr), | ||||
| 			} | ||||
| 			if !w.wr.valid() { | ||||
| 				w.post(&pb.WatchResponse{WatchId: -1, Created: true, Canceled: true}) | ||||
| 				wps.mu.Unlock() | ||||
| 				continue | ||||
| 			} | ||||
| 			wps.nextWatcherID++ | ||||
| 			w.nextrev = cr.StartRevision | ||||
| 			wps.watchers[w.id] = w | ||||
| 			wps.ranges.add(w) | ||||
| 			wps.mu.Unlock() | ||||
| 			wps.lg.Debug("create watcher", zap.String("key", w.wr.key), zap.String("end", w.wr.end), zap.Int64("watcherId", wps.nextWatcherID)) | ||||
| 		case *pb.WatchRequest_CancelRequest: | ||||
| 			wps.delete(uv.CancelRequest.WatchId) | ||||
| 			wps.lg.Debug("cancel watcher", zap.Int64("watcherId", uv.CancelRequest.WatchId)) | ||||
| 		default: | ||||
| 			// Panic or Fatalf would allow to network clients to crash the serve remotely. | ||||
| 			wps.lg.Error("not supported request type by gRPC proxy", zap.Stringer("request", req)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (wps *watchProxyStream) sendLoop() { | ||||
| 	for { | ||||
| 		select { | ||||
| 		case wresp, ok := <-wps.watchCh: | ||||
| 			if !ok { | ||||
| 				return | ||||
| 			} | ||||
| 			if err := wps.stream.Send(wresp); err != nil { | ||||
| 				return | ||||
| 			} | ||||
| 		case <-wps.ctx.Done(): | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (wps *watchProxyStream) delete(id int64) { | ||||
| 	wps.mu.Lock() | ||||
| 	defer wps.mu.Unlock() | ||||
|  | ||||
| 	w, ok := wps.watchers[id] | ||||
| 	if !ok { | ||||
| 		return | ||||
| 	} | ||||
| 	wps.ranges.delete(w) | ||||
| 	delete(wps.watchers, id) | ||||
| 	resp := &pb.WatchResponse{ | ||||
| 		Header:   &w.lastHeader, | ||||
| 		WatchId:  id, | ||||
| 		Canceled: true, | ||||
| 	} | ||||
| 	wps.watchCh <- resp | ||||
| } | ||||
							
								
								
									
										166
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcast.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										166
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcast.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,166 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	clientv3 "go.etcd.io/etcd/client/v3" | ||||
|  | ||||
| 	"go.uber.org/zap" | ||||
| ) | ||||
|  | ||||
| // watchBroadcast broadcasts a server watcher to many client watchers. | ||||
| type watchBroadcast struct { | ||||
| 	// cancel stops the underlying etcd server watcher and closes ch. | ||||
| 	cancel context.CancelFunc | ||||
| 	donec  chan struct{} | ||||
|  | ||||
| 	// mu protects rev and receivers. | ||||
| 	mu sync.RWMutex | ||||
| 	// nextrev is the minimum expected next revision of the watcher on ch. | ||||
| 	nextrev int64 | ||||
| 	// receivers contains all the client-side watchers to serve. | ||||
| 	receivers map[*watcher]struct{} | ||||
| 	// responses counts the number of responses | ||||
| 	responses int | ||||
| 	lg        *zap.Logger | ||||
| } | ||||
|  | ||||
| func newWatchBroadcast(lg *zap.Logger, wp *watchProxy, w *watcher, update func(*watchBroadcast)) *watchBroadcast { | ||||
| 	cctx, cancel := context.WithCancel(wp.ctx) | ||||
| 	wb := &watchBroadcast{ | ||||
| 		cancel:    cancel, | ||||
| 		nextrev:   w.nextrev, | ||||
| 		receivers: make(map[*watcher]struct{}), | ||||
| 		donec:     make(chan struct{}), | ||||
| 		lg:        lg, | ||||
| 	} | ||||
| 	wb.add(w) | ||||
| 	go func() { | ||||
| 		defer close(wb.donec) | ||||
|  | ||||
| 		opts := []clientv3.OpOption{ | ||||
| 			clientv3.WithRange(w.wr.end), | ||||
| 			clientv3.WithProgressNotify(), | ||||
| 			clientv3.WithRev(wb.nextrev), | ||||
| 			clientv3.WithPrevKV(), | ||||
| 			clientv3.WithCreatedNotify(), | ||||
| 		} | ||||
|  | ||||
| 		cctx = withClientAuthToken(cctx, w.wps.stream.Context()) | ||||
|  | ||||
| 		wch := wp.cw.Watch(cctx, w.wr.key, opts...) | ||||
| 		wp.lg.Debug("watch", zap.String("key", w.wr.key)) | ||||
|  | ||||
| 		for wr := range wch { | ||||
| 			wb.bcast(wr) | ||||
| 			update(wb) | ||||
| 		} | ||||
| 	}() | ||||
| 	return wb | ||||
| } | ||||
|  | ||||
| func (wb *watchBroadcast) bcast(wr clientv3.WatchResponse) { | ||||
| 	wb.mu.Lock() | ||||
| 	defer wb.mu.Unlock() | ||||
| 	// watchers start on the given revision, if any; ignore header rev on create | ||||
| 	if wb.responses > 0 || wb.nextrev == 0 { | ||||
| 		wb.nextrev = wr.Header.Revision + 1 | ||||
| 	} | ||||
| 	wb.responses++ | ||||
| 	for r := range wb.receivers { | ||||
| 		r.send(wr) | ||||
| 	} | ||||
| 	if len(wb.receivers) > 0 { | ||||
| 		eventsCoalescing.Add(float64(len(wb.receivers) - 1)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // add puts a watcher into receiving a broadcast if its revision at least | ||||
| // meets the broadcast revision. Returns true if added. | ||||
| func (wb *watchBroadcast) add(w *watcher) bool { | ||||
| 	wb.mu.Lock() | ||||
| 	defer wb.mu.Unlock() | ||||
| 	if wb.nextrev > w.nextrev || (wb.nextrev == 0 && w.nextrev != 0) { | ||||
| 		// wb is too far ahead, w will miss events | ||||
| 		// or wb is being established with a current watcher | ||||
| 		return false | ||||
| 	} | ||||
| 	if wb.responses == 0 { | ||||
| 		// Newly created; create event will be sent by etcd. | ||||
| 		wb.receivers[w] = struct{}{} | ||||
| 		return true | ||||
| 	} | ||||
| 	// already sent by etcd; emulate create event | ||||
| 	ok := w.post(&pb.WatchResponse{ | ||||
| 		Header: &pb.ResponseHeader{ | ||||
| 			// todo: fill in ClusterId | ||||
| 			// todo: fill in MemberId: | ||||
| 			Revision: w.nextrev, | ||||
| 			// todo: fill in RaftTerm: | ||||
| 		}, | ||||
| 		WatchId: w.id, | ||||
| 		Created: true, | ||||
| 	}) | ||||
| 	if !ok { | ||||
| 		return false | ||||
| 	} | ||||
| 	wb.receivers[w] = struct{}{} | ||||
| 	watchersCoalescing.Inc() | ||||
|  | ||||
| 	return true | ||||
| } | ||||
| func (wb *watchBroadcast) delete(w *watcher) { | ||||
| 	wb.mu.Lock() | ||||
| 	defer wb.mu.Unlock() | ||||
| 	if _, ok := wb.receivers[w]; !ok { | ||||
| 		panic("deleting missing watcher from broadcast") | ||||
| 	} | ||||
| 	delete(wb.receivers, w) | ||||
| 	if len(wb.receivers) > 0 { | ||||
| 		// do not dec the only left watcher for coalescing. | ||||
| 		watchersCoalescing.Dec() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (wb *watchBroadcast) size() int { | ||||
| 	wb.mu.RLock() | ||||
| 	defer wb.mu.RUnlock() | ||||
| 	return len(wb.receivers) | ||||
| } | ||||
|  | ||||
| func (wb *watchBroadcast) empty() bool { return wb.size() == 0 } | ||||
|  | ||||
| func (wb *watchBroadcast) stop() { | ||||
| 	if !wb.empty() { | ||||
| 		// do not dec the only left watcher for coalescing. | ||||
| 		watchersCoalescing.Sub(float64(wb.size() - 1)) | ||||
| 	} | ||||
|  | ||||
| 	wb.cancel() | ||||
|  | ||||
| 	select { | ||||
| 	case <-wb.donec: | ||||
| 		// watchProxyStream will hold watchRanges global mutex lock all the time if client failed to cancel etcd watchers. | ||||
| 		// and it will cause the watch proxy to not work. | ||||
| 		// please see pr https://github.com/etcd-io/etcd/pull/12030 to get more detail info. | ||||
| 	case <-time.After(time.Second): | ||||
| 		wb.lg.Error("failed to cancel etcd watcher") | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										135
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcasts.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										135
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcasts.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,135 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| type watchBroadcasts struct { | ||||
| 	wp *watchProxy | ||||
|  | ||||
| 	// mu protects bcasts and watchers from the coalesce loop. | ||||
| 	mu       sync.Mutex | ||||
| 	bcasts   map[*watchBroadcast]struct{} | ||||
| 	watchers map[*watcher]*watchBroadcast | ||||
|  | ||||
| 	updatec chan *watchBroadcast | ||||
| 	donec   chan struct{} | ||||
| } | ||||
|  | ||||
| // maxCoalesceRecievers prevents a popular watchBroadcast from being coalseced. | ||||
| const maxCoalesceReceivers = 5 | ||||
|  | ||||
| func newWatchBroadcasts(wp *watchProxy) *watchBroadcasts { | ||||
| 	wbs := &watchBroadcasts{ | ||||
| 		wp:       wp, | ||||
| 		bcasts:   make(map[*watchBroadcast]struct{}), | ||||
| 		watchers: make(map[*watcher]*watchBroadcast), | ||||
| 		updatec:  make(chan *watchBroadcast, 1), | ||||
| 		donec:    make(chan struct{}), | ||||
| 	} | ||||
| 	go func() { | ||||
| 		defer close(wbs.donec) | ||||
| 		for wb := range wbs.updatec { | ||||
| 			wbs.coalesce(wb) | ||||
| 		} | ||||
| 	}() | ||||
| 	return wbs | ||||
| } | ||||
|  | ||||
| func (wbs *watchBroadcasts) coalesce(wb *watchBroadcast) { | ||||
| 	if wb.size() >= maxCoalesceReceivers { | ||||
| 		return | ||||
| 	} | ||||
| 	wbs.mu.Lock() | ||||
| 	for wbswb := range wbs.bcasts { | ||||
| 		if wbswb == wb { | ||||
| 			continue | ||||
| 		} | ||||
| 		wb.mu.Lock() | ||||
| 		wbswb.mu.Lock() | ||||
| 		// 1. check if wbswb is behind wb so it won't skip any events in wb | ||||
| 		// 2. ensure wbswb started; nextrev == 0 may mean wbswb is waiting | ||||
| 		// for a current watcher and expects a create event from the server. | ||||
| 		if wb.nextrev >= wbswb.nextrev && wbswb.responses > 0 { | ||||
| 			for w := range wb.receivers { | ||||
| 				wbswb.receivers[w] = struct{}{} | ||||
| 				wbs.watchers[w] = wbswb | ||||
| 			} | ||||
| 			wb.receivers = nil | ||||
| 		} | ||||
| 		wbswb.mu.Unlock() | ||||
| 		wb.mu.Unlock() | ||||
| 		if wb.empty() { | ||||
| 			delete(wbs.bcasts, wb) | ||||
| 			wb.stop() | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	wbs.mu.Unlock() | ||||
| } | ||||
|  | ||||
| func (wbs *watchBroadcasts) add(w *watcher) { | ||||
| 	wbs.mu.Lock() | ||||
| 	defer wbs.mu.Unlock() | ||||
| 	// find fitting bcast | ||||
| 	for wb := range wbs.bcasts { | ||||
| 		if wb.add(w) { | ||||
| 			wbs.watchers[w] = wb | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	// no fit; create a bcast | ||||
| 	wb := newWatchBroadcast(wbs.wp.lg, wbs.wp, w, wbs.update) | ||||
| 	wbs.watchers[w] = wb | ||||
| 	wbs.bcasts[wb] = struct{}{} | ||||
| } | ||||
|  | ||||
| // delete removes a watcher and returns the number of remaining watchers. | ||||
| func (wbs *watchBroadcasts) delete(w *watcher) int { | ||||
| 	wbs.mu.Lock() | ||||
| 	defer wbs.mu.Unlock() | ||||
|  | ||||
| 	wb, ok := wbs.watchers[w] | ||||
| 	if !ok { | ||||
| 		panic("deleting missing watcher from broadcasts") | ||||
| 	} | ||||
| 	delete(wbs.watchers, w) | ||||
| 	wb.delete(w) | ||||
| 	if wb.empty() { | ||||
| 		delete(wbs.bcasts, wb) | ||||
| 		wb.stop() | ||||
| 	} | ||||
| 	return len(wbs.bcasts) | ||||
| } | ||||
|  | ||||
| func (wbs *watchBroadcasts) stop() { | ||||
| 	wbs.mu.Lock() | ||||
| 	for wb := range wbs.bcasts { | ||||
| 		wb.stop() | ||||
| 	} | ||||
| 	wbs.bcasts = nil | ||||
| 	close(wbs.updatec) | ||||
| 	wbs.mu.Unlock() | ||||
| 	<-wbs.donec | ||||
| } | ||||
|  | ||||
| func (wbs *watchBroadcasts) update(wb *watchBroadcast) { | ||||
| 	select { | ||||
| 	case wbs.updatec <- wb: | ||||
| 	default: | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										69
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_ranges.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_ranges.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,69 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| // watchRanges tracks all open watches for the proxy. | ||||
| type watchRanges struct { | ||||
| 	wp *watchProxy | ||||
|  | ||||
| 	mu     sync.Mutex | ||||
| 	bcasts map[watchRange]*watchBroadcasts | ||||
| } | ||||
|  | ||||
| func newWatchRanges(wp *watchProxy) *watchRanges { | ||||
| 	return &watchRanges{ | ||||
| 		wp:     wp, | ||||
| 		bcasts: make(map[watchRange]*watchBroadcasts), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (wrs *watchRanges) add(w *watcher) { | ||||
| 	wrs.mu.Lock() | ||||
| 	defer wrs.mu.Unlock() | ||||
|  | ||||
| 	if wbs := wrs.bcasts[w.wr]; wbs != nil { | ||||
| 		wbs.add(w) | ||||
| 		return | ||||
| 	} | ||||
| 	wbs := newWatchBroadcasts(wrs.wp) | ||||
| 	wrs.bcasts[w.wr] = wbs | ||||
| 	wbs.add(w) | ||||
| } | ||||
|  | ||||
| func (wrs *watchRanges) delete(w *watcher) { | ||||
| 	wrs.mu.Lock() | ||||
| 	defer wrs.mu.Unlock() | ||||
| 	wbs, ok := wrs.bcasts[w.wr] | ||||
| 	if !ok { | ||||
| 		panic("deleting missing range") | ||||
| 	} | ||||
| 	if wbs.delete(w) == 0 { | ||||
| 		wbs.stop() | ||||
| 		delete(wrs.bcasts, w.wr) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (wrs *watchRanges) stop() { | ||||
| 	wrs.mu.Lock() | ||||
| 	defer wrs.mu.Unlock() | ||||
| 	for _, wb := range wrs.bcasts { | ||||
| 		wb.stop() | ||||
| 	} | ||||
| 	wrs.bcasts = nil | ||||
| } | ||||
							
								
								
									
										130
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watcher.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										130
									
								
								vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watcher.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,130 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 grpcproxy | ||||
|  | ||||
| import ( | ||||
| 	"time" | ||||
|  | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/api/v3/mvccpb" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/server/v3/mvcc" | ||||
| ) | ||||
|  | ||||
| type watchRange struct { | ||||
| 	key, end string | ||||
| } | ||||
|  | ||||
| func (wr *watchRange) valid() bool { | ||||
| 	return len(wr.end) == 0 || wr.end > wr.key || (wr.end[0] == 0 && len(wr.end) == 1) | ||||
| } | ||||
|  | ||||
| type watcher struct { | ||||
| 	// user configuration | ||||
|  | ||||
| 	wr       watchRange | ||||
| 	filters  []mvcc.FilterFunc | ||||
| 	progress bool | ||||
| 	prevKV   bool | ||||
|  | ||||
| 	// id is the id returned to the client on its watch stream. | ||||
| 	id int64 | ||||
| 	// nextrev is the minimum expected next event revision. | ||||
| 	nextrev int64 | ||||
| 	// lastHeader has the last header sent over the stream. | ||||
| 	lastHeader pb.ResponseHeader | ||||
|  | ||||
| 	// wps is the parent. | ||||
| 	wps *watchProxyStream | ||||
| } | ||||
|  | ||||
| // send filters out repeated events by discarding revisions older | ||||
| // than the last one sent over the watch channel. | ||||
| func (w *watcher) send(wr clientv3.WatchResponse) { | ||||
| 	if wr.IsProgressNotify() && !w.progress { | ||||
| 		return | ||||
| 	} | ||||
| 	if w.nextrev > wr.Header.Revision && len(wr.Events) > 0 { | ||||
| 		return | ||||
| 	} | ||||
| 	if w.nextrev == 0 { | ||||
| 		// current watch; expect updates following this revision | ||||
| 		w.nextrev = wr.Header.Revision + 1 | ||||
| 	} | ||||
|  | ||||
| 	events := make([]*mvccpb.Event, 0, len(wr.Events)) | ||||
|  | ||||
| 	var lastRev int64 | ||||
| 	for i := range wr.Events { | ||||
| 		ev := (*mvccpb.Event)(wr.Events[i]) | ||||
| 		if ev.Kv.ModRevision < w.nextrev { | ||||
| 			continue | ||||
| 		} else { | ||||
| 			// We cannot update w.rev here. | ||||
| 			// txn can have multiple events with the same rev. | ||||
| 			// If w.nextrev updates here, it would skip events in the same txn. | ||||
| 			lastRev = ev.Kv.ModRevision | ||||
| 		} | ||||
|  | ||||
| 		filtered := false | ||||
| 		for _, filter := range w.filters { | ||||
| 			if filter(*ev) { | ||||
| 				filtered = true | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		if filtered { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if !w.prevKV { | ||||
| 			evCopy := *ev | ||||
| 			evCopy.PrevKv = nil | ||||
| 			ev = &evCopy | ||||
| 		} | ||||
| 		events = append(events, ev) | ||||
| 	} | ||||
|  | ||||
| 	if lastRev >= w.nextrev { | ||||
| 		w.nextrev = lastRev + 1 | ||||
| 	} | ||||
|  | ||||
| 	// all events are filtered out? | ||||
| 	if !wr.IsProgressNotify() && !wr.Created && len(events) == 0 && wr.CompactRevision == 0 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	w.lastHeader = wr.Header | ||||
| 	w.post(&pb.WatchResponse{ | ||||
| 		Header:          &wr.Header, | ||||
| 		Created:         wr.Created, | ||||
| 		CompactRevision: wr.CompactRevision, | ||||
| 		Canceled:        wr.Canceled, | ||||
| 		WatchId:         w.id, | ||||
| 		Events:          events, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // post puts a watch response on the watcher's proxy stream channel | ||||
| func (w *watcher) post(wr *pb.WatchResponse) bool { | ||||
| 	select { | ||||
| 	case w.wps.watchCh <- wr: | ||||
| 	case <-time.After(50 * time.Millisecond): | ||||
| 		w.wps.cancel() | ||||
| 		w.wps.lg.Error("failed to put a watch response on the watcher's proxy stream channel,err is timeout") | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
							
								
								
									
										202
									
								
								vendor/go.etcd.io/etcd/tests/v3/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										202
									
								
								vendor/go.etcd.io/etcd/tests/v3/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -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. | ||||
							
								
								
									
										228
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/bridge.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										228
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/bridge.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,228 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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 integration | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"sync" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/pkg/v3/transport" | ||||
| ) | ||||
|  | ||||
| // bridge creates a unix socket bridge to another unix socket, making it possible | ||||
| // to disconnect grpc network connections without closing the logical grpc connection. | ||||
| type bridge struct { | ||||
| 	inaddr  string | ||||
| 	outaddr string | ||||
| 	l       net.Listener | ||||
| 	conns   map[*bridgeConn]struct{} | ||||
|  | ||||
| 	stopc      chan struct{} | ||||
| 	pausec     chan struct{} | ||||
| 	blackholec chan struct{} | ||||
| 	wg         sync.WaitGroup | ||||
|  | ||||
| 	mu sync.Mutex | ||||
| } | ||||
|  | ||||
| func newBridge(addr string) (*bridge, error) { | ||||
| 	b := &bridge{ | ||||
| 		// bridge "port" is ("%05d%05d0", port, pid) since go1.8 expects the port to be a number | ||||
| 		inaddr:     addr + "0", | ||||
| 		outaddr:    addr, | ||||
| 		conns:      make(map[*bridgeConn]struct{}), | ||||
| 		stopc:      make(chan struct{}), | ||||
| 		pausec:     make(chan struct{}), | ||||
| 		blackholec: make(chan struct{}), | ||||
| 	} | ||||
| 	close(b.pausec) | ||||
|  | ||||
| 	l, err := transport.NewUnixListener(b.inaddr) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("listen failed on socket %s (%v)", addr, err) | ||||
| 	} | ||||
| 	b.l = l | ||||
| 	b.wg.Add(1) | ||||
| 	go b.serveListen() | ||||
| 	return b, nil | ||||
| } | ||||
|  | ||||
| func (b *bridge) URL() string { return "unix://" + b.inaddr } | ||||
|  | ||||
| func (b *bridge) Close() { | ||||
| 	b.l.Close() | ||||
| 	b.mu.Lock() | ||||
| 	select { | ||||
| 	case <-b.stopc: | ||||
| 	default: | ||||
| 		close(b.stopc) | ||||
| 	} | ||||
| 	b.mu.Unlock() | ||||
| 	b.wg.Wait() | ||||
| } | ||||
|  | ||||
| func (b *bridge) Reset() { | ||||
| 	b.mu.Lock() | ||||
| 	defer b.mu.Unlock() | ||||
| 	for bc := range b.conns { | ||||
| 		bc.Close() | ||||
| 	} | ||||
| 	b.conns = make(map[*bridgeConn]struct{}) | ||||
| } | ||||
|  | ||||
| func (b *bridge) Pause() { | ||||
| 	b.mu.Lock() | ||||
| 	b.pausec = make(chan struct{}) | ||||
| 	b.mu.Unlock() | ||||
| } | ||||
|  | ||||
| func (b *bridge) Unpause() { | ||||
| 	b.mu.Lock() | ||||
| 	select { | ||||
| 	case <-b.pausec: | ||||
| 	default: | ||||
| 		close(b.pausec) | ||||
| 	} | ||||
| 	b.mu.Unlock() | ||||
| } | ||||
|  | ||||
| func (b *bridge) serveListen() { | ||||
| 	defer func() { | ||||
| 		b.l.Close() | ||||
| 		b.mu.Lock() | ||||
| 		for bc := range b.conns { | ||||
| 			bc.Close() | ||||
| 		} | ||||
| 		b.mu.Unlock() | ||||
| 		b.wg.Done() | ||||
| 	}() | ||||
|  | ||||
| 	for { | ||||
| 		inc, ierr := b.l.Accept() | ||||
| 		if ierr != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		b.mu.Lock() | ||||
| 		pausec := b.pausec | ||||
| 		b.mu.Unlock() | ||||
| 		select { | ||||
| 		case <-b.stopc: | ||||
| 			inc.Close() | ||||
| 			return | ||||
| 		case <-pausec: | ||||
| 		} | ||||
|  | ||||
| 		outc, oerr := net.Dial("unix", b.outaddr) | ||||
| 		if oerr != nil { | ||||
| 			inc.Close() | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		bc := &bridgeConn{inc, outc, make(chan struct{})} | ||||
| 		b.wg.Add(1) | ||||
| 		b.mu.Lock() | ||||
| 		b.conns[bc] = struct{}{} | ||||
| 		go b.serveConn(bc) | ||||
| 		b.mu.Unlock() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *bridge) serveConn(bc *bridgeConn) { | ||||
| 	defer func() { | ||||
| 		close(bc.donec) | ||||
| 		bc.Close() | ||||
| 		b.mu.Lock() | ||||
| 		delete(b.conns, bc) | ||||
| 		b.mu.Unlock() | ||||
| 		b.wg.Done() | ||||
| 	}() | ||||
|  | ||||
| 	var wg sync.WaitGroup | ||||
| 	wg.Add(2) | ||||
| 	go func() { | ||||
| 		b.ioCopy(bc.out, bc.in) | ||||
| 		bc.close() | ||||
| 		wg.Done() | ||||
| 	}() | ||||
| 	go func() { | ||||
| 		b.ioCopy(bc.in, bc.out) | ||||
| 		bc.close() | ||||
| 		wg.Done() | ||||
| 	}() | ||||
| 	wg.Wait() | ||||
| } | ||||
|  | ||||
| type bridgeConn struct { | ||||
| 	in    net.Conn | ||||
| 	out   net.Conn | ||||
| 	donec chan struct{} | ||||
| } | ||||
|  | ||||
| func (bc *bridgeConn) Close() { | ||||
| 	bc.close() | ||||
| 	<-bc.donec | ||||
| } | ||||
|  | ||||
| func (bc *bridgeConn) close() { | ||||
| 	bc.in.Close() | ||||
| 	bc.out.Close() | ||||
| } | ||||
|  | ||||
| func (b *bridge) Blackhole() { | ||||
| 	b.mu.Lock() | ||||
| 	close(b.blackholec) | ||||
| 	b.mu.Unlock() | ||||
| } | ||||
|  | ||||
| func (b *bridge) Unblackhole() { | ||||
| 	b.mu.Lock() | ||||
| 	for bc := range b.conns { | ||||
| 		bc.Close() | ||||
| 	} | ||||
| 	b.conns = make(map[*bridgeConn]struct{}) | ||||
| 	b.blackholec = make(chan struct{}) | ||||
| 	b.mu.Unlock() | ||||
| } | ||||
|  | ||||
| // ref. https://github.com/golang/go/blob/master/src/io/io.go copyBuffer | ||||
| func (b *bridge) ioCopy(dst io.Writer, src io.Reader) (err error) { | ||||
| 	buf := make([]byte, 32*1024) | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-b.blackholec: | ||||
| 			io.Copy(ioutil.Discard, src) | ||||
| 			return nil | ||||
| 		default: | ||||
| 		} | ||||
| 		nr, er := src.Read(buf) | ||||
| 		if nr > 0 { | ||||
| 			nw, ew := dst.Write(buf[0:nr]) | ||||
| 			if ew != nil { | ||||
| 				return ew | ||||
| 			} | ||||
| 			if nr != nw { | ||||
| 				return io.ErrShortWrite | ||||
| 			} | ||||
| 		} | ||||
| 		if er != nil { | ||||
| 			err = er | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										1533
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/cluster.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1533
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/cluster.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										46
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/cluster_direct.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/cluster_direct.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,46 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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:build !cluster_proxy | ||||
| // +build !cluster_proxy | ||||
|  | ||||
| package integration | ||||
|  | ||||
| import ( | ||||
| 	pb "go.etcd.io/etcd/api/v3/etcdserverpb" | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb" | ||||
| 	"go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb" | ||||
| 	"go.uber.org/zap" | ||||
| ) | ||||
|  | ||||
| const ThroughProxy = false | ||||
|  | ||||
| func toGRPC(c *clientv3.Client) grpcAPI { | ||||
| 	return grpcAPI{ | ||||
| 		pb.NewClusterClient(c.ActiveConnection()), | ||||
| 		pb.NewKVClient(c.ActiveConnection()), | ||||
| 		pb.NewLeaseClient(c.ActiveConnection()), | ||||
| 		pb.NewWatchClient(c.ActiveConnection()), | ||||
| 		pb.NewMaintenanceClient(c.ActiveConnection()), | ||||
| 		pb.NewAuthClient(c.ActiveConnection()), | ||||
| 		v3lockpb.NewLockClient(c.ActiveConnection()), | ||||
| 		v3electionpb.NewElectionClient(c.ActiveConnection()), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newClientV3(cfg clientv3.Config, lg *zap.Logger) (*clientv3.Client, error) { | ||||
| 	cfg.Logger = lg | ||||
| 	return clientv3.New(cfg) | ||||
| } | ||||
							
								
								
									
										132
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/cluster_proxy.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										132
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/cluster_proxy.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,132 +0,0 @@ | ||||
| // Copyright 2016 The etcd 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:build cluster_proxy | ||||
| // +build cluster_proxy | ||||
|  | ||||
| package integration | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/client/v3/namespace" | ||||
| 	"go.etcd.io/etcd/server/v3/proxy/grpcproxy" | ||||
| 	"go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter" | ||||
| 	"go.uber.org/zap" | ||||
| ) | ||||
|  | ||||
| const ThroughProxy = true | ||||
|  | ||||
| var ( | ||||
| 	pmu     sync.Mutex | ||||
| 	proxies map[*clientv3.Client]grpcClientProxy = make(map[*clientv3.Client]grpcClientProxy) | ||||
| ) | ||||
|  | ||||
| const proxyNamespace = "proxy-namespace" | ||||
|  | ||||
| type grpcClientProxy struct { | ||||
| 	ctx       context.Context | ||||
| 	ctxCancel func() | ||||
| 	grpc      grpcAPI | ||||
| 	wdonec    <-chan struct{} | ||||
| 	kvdonec   <-chan struct{} | ||||
| 	lpdonec   <-chan struct{} | ||||
| } | ||||
|  | ||||
| func toGRPC(c *clientv3.Client) grpcAPI { | ||||
| 	pmu.Lock() | ||||
| 	defer pmu.Unlock() | ||||
|  | ||||
| 	// dedicated context bound to 'grpc-proxy' lifetype | ||||
| 	// (so in practice lifetime of the client connection to the proxy). | ||||
| 	// TODO: Refactor to a separate clientv3.Client instance instead of the context alone. | ||||
| 	ctx, ctxCancel := context.WithCancel(context.WithValue(context.TODO(), "_name", "grpcProxyContext")) | ||||
|  | ||||
| 	lg := c.GetLogger() | ||||
|  | ||||
| 	if v, ok := proxies[c]; ok { | ||||
| 		return v.grpc | ||||
| 	} | ||||
|  | ||||
| 	// test namespacing proxy | ||||
| 	c.KV = namespace.NewKV(c.KV, proxyNamespace) | ||||
| 	c.Watcher = namespace.NewWatcher(c.Watcher, proxyNamespace) | ||||
| 	c.Lease = namespace.NewLease(c.Lease, proxyNamespace) | ||||
| 	// test coalescing/caching proxy | ||||
| 	kvp, kvpch := grpcproxy.NewKvProxy(c) | ||||
| 	wp, wpch := grpcproxy.NewWatchProxy(ctx, lg, c) | ||||
| 	lp, lpch := grpcproxy.NewLeaseProxy(ctx, c) | ||||
| 	mp := grpcproxy.NewMaintenanceProxy(c) | ||||
| 	clp, _ := grpcproxy.NewClusterProxy(lg, c, "", "") // without registering proxy URLs | ||||
| 	authp := grpcproxy.NewAuthProxy(c) | ||||
| 	lockp := grpcproxy.NewLockProxy(c) | ||||
| 	electp := grpcproxy.NewElectionProxy(c) | ||||
|  | ||||
| 	grpc := grpcAPI{ | ||||
| 		adapter.ClusterServerToClusterClient(clp), | ||||
| 		adapter.KvServerToKvClient(kvp), | ||||
| 		adapter.LeaseServerToLeaseClient(lp), | ||||
| 		adapter.WatchServerToWatchClient(wp), | ||||
| 		adapter.MaintenanceServerToMaintenanceClient(mp), | ||||
| 		adapter.AuthServerToAuthClient(authp), | ||||
| 		adapter.LockServerToLockClient(lockp), | ||||
| 		adapter.ElectionServerToElectionClient(electp), | ||||
| 	} | ||||
| 	proxies[c] = grpcClientProxy{ctx: ctx, ctxCancel: ctxCancel, grpc: grpc, wdonec: wpch, kvdonec: kvpch, lpdonec: lpch} | ||||
| 	return grpc | ||||
| } | ||||
|  | ||||
| type proxyCloser struct { | ||||
| 	clientv3.Watcher | ||||
| 	proxyCtxCancel func() | ||||
| 	wdonec         <-chan struct{} | ||||
| 	kvdonec        <-chan struct{} | ||||
| 	lclose         func() | ||||
| 	lpdonec        <-chan struct{} | ||||
| } | ||||
|  | ||||
| func (pc *proxyCloser) Close() error { | ||||
| 	pc.proxyCtxCancel() | ||||
| 	<-pc.kvdonec | ||||
| 	err := pc.Watcher.Close() | ||||
| 	<-pc.wdonec | ||||
| 	pc.lclose() | ||||
| 	<-pc.lpdonec | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func newClientV3(cfg clientv3.Config, lg *zap.Logger) (*clientv3.Client, error) { | ||||
| 	cfg.Logger = lg | ||||
| 	c, err := clientv3.New(cfg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	rpc := toGRPC(c) | ||||
| 	c.KV = clientv3.NewKVFromKVClient(rpc.KV, c) | ||||
| 	pmu.Lock() | ||||
| 	lc := c.Lease | ||||
| 	c.Lease = clientv3.NewLeaseFromLeaseClient(rpc.Lease, c, cfg.DialTimeout) | ||||
| 	c.Watcher = &proxyCloser{ | ||||
| 		Watcher:        clientv3.NewWatchFromWatchClient(rpc.Watch, c), | ||||
| 		wdonec:         proxies[c].wdonec, | ||||
| 		kvdonec:        proxies[c].kvdonec, | ||||
| 		lclose:         func() { lc.Close() }, | ||||
| 		lpdonec:        proxies[c].lpdonec, | ||||
| 		proxyCtxCancel: proxies[c].ctxCancel, | ||||
| 	} | ||||
| 	pmu.Unlock() | ||||
| 	return c, nil | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,25 +0,0 @@ | ||||
| // Copyright 2015 The etcd 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 integration implements tests built upon embedded etcd, and focus on | ||||
| etcd correctness. | ||||
|  | ||||
| Features/goals of the integration tests: | ||||
| 1. test the whole code base except command-line parsing. | ||||
| 2. check internal data, including raft, store and etc. | ||||
| 3. based on goroutines, which is faster than process. | ||||
| 4. mainly tests user behavior and user-facing API. | ||||
| */ | ||||
| package integration | ||||
							
								
								
									
										120
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/lazy_cluster.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										120
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/lazy_cluster.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,120 +0,0 @@ | ||||
| // Copyright 2020 The etcd 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 integration | ||||
|  | ||||
| import ( | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"go.etcd.io/etcd/client/pkg/v3/testutil" | ||||
| 	"go.etcd.io/etcd/client/pkg/v3/transport" | ||||
| ) | ||||
|  | ||||
| // Infrastructure to provision a single shared cluster for tests - only | ||||
| // when its needed. | ||||
| // | ||||
| // See ./tests/integration/clientv3/examples/main_test.go for canonical usage. | ||||
| // Please notice that the shared (LazyCluster's) state is preserved between | ||||
| // testcases, so left-over state might has cross-testcase effects. | ||||
| // Prefer dedicated clusters for substancial test-cases. | ||||
|  | ||||
| type LazyCluster interface { | ||||
| 	// EndpointsV2 - exposes connection points for client v2. | ||||
| 	// Calls to this method might initialize the cluster. | ||||
| 	EndpointsV2() []string | ||||
|  | ||||
| 	// EndpointsV3 - exposes connection points for client v3. | ||||
| 	// Calls to this method might initialize the cluster. | ||||
| 	EndpointsV3() []string | ||||
|  | ||||
| 	// Cluster - calls to this method might initialize the cluster. | ||||
| 	Cluster() *ClusterV3 | ||||
|  | ||||
| 	// Transport - call to this method might initialize the cluster. | ||||
| 	Transport() *http.Transport | ||||
|  | ||||
| 	Terminate() | ||||
|  | ||||
| 	TB() testutil.TB | ||||
| } | ||||
|  | ||||
| type lazyCluster struct { | ||||
| 	cfg       ClusterConfig | ||||
| 	cluster   *ClusterV3 | ||||
| 	transport *http.Transport | ||||
| 	once      sync.Once | ||||
| 	tb        testutil.TB | ||||
| 	closer    func() | ||||
| } | ||||
|  | ||||
| // NewLazyCluster returns a new test cluster handler that gets created on the | ||||
| // first call to GetEndpoints() or GetTransport() | ||||
| func NewLazyCluster() LazyCluster { | ||||
| 	return NewLazyClusterWithConfig(ClusterConfig{Size: 1}) | ||||
| } | ||||
|  | ||||
| // NewLazyClusterWithConfig returns a new test cluster handler that gets created | ||||
| // on the first call to GetEndpoints() or GetTransport() | ||||
| func NewLazyClusterWithConfig(cfg ClusterConfig) LazyCluster { | ||||
| 	tb, closer := testutil.NewTestingTBProthesis("lazy_cluster") | ||||
| 	return &lazyCluster{cfg: cfg, tb: tb, closer: closer} | ||||
| } | ||||
|  | ||||
| func (lc *lazyCluster) mustLazyInit() { | ||||
| 	lc.once.Do(func() { | ||||
| 		var err error | ||||
| 		lc.transport, err = transport.NewTransport(transport.TLSInfo{}, time.Second) | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		lc.cluster = NewClusterV3(lc.tb, &lc.cfg) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (lc *lazyCluster) Terminate() { | ||||
| 	lc.tb.Logf("Terminating...") | ||||
| 	if lc != nil && lc.cluster != nil { | ||||
| 		lc.cluster.Terminate(nil) | ||||
| 		lc.cluster = nil | ||||
| 	} | ||||
| 	if lc.closer != nil { | ||||
| 		lc.tb.Logf("Closer...") | ||||
| 		lc.closer() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (lc *lazyCluster) EndpointsV2() []string { | ||||
| 	return []string{lc.Cluster().Members[0].URL()} | ||||
| } | ||||
|  | ||||
| func (lc *lazyCluster) EndpointsV3() []string { | ||||
| 	return lc.Cluster().Client(0).Endpoints() | ||||
| } | ||||
|  | ||||
| func (lc *lazyCluster) Cluster() *ClusterV3 { | ||||
| 	lc.mustLazyInit() | ||||
| 	return lc.cluster | ||||
| } | ||||
|  | ||||
| func (lc *lazyCluster) Transport() *http.Transport { | ||||
| 	lc.mustLazyInit() | ||||
| 	return lc.transport | ||||
| } | ||||
|  | ||||
| func (lc *lazyCluster) TB() testutil.TB { | ||||
| 	return lc.tb | ||||
| } | ||||
							
								
								
									
										136
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/testing.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										136
									
								
								vendor/go.etcd.io/etcd/tests/v3/integration/testing.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,136 +0,0 @@ | ||||
| // Copyright 2021 The etcd 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 integration | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"testing" | ||||
|  | ||||
| 	grpc_logsettable "github.com/grpc-ecosystem/go-grpc-middleware/logging/settable" | ||||
| 	"go.etcd.io/etcd/client/pkg/v3/testutil" | ||||
| 	clientv3 "go.etcd.io/etcd/client/v3" | ||||
| 	"go.etcd.io/etcd/server/v3/embed" | ||||
| 	"go.etcd.io/etcd/server/v3/verify" | ||||
| 	"go.uber.org/zap/zapcore" | ||||
| 	"go.uber.org/zap/zapgrpc" | ||||
| 	"go.uber.org/zap/zaptest" | ||||
| ) | ||||
|  | ||||
| var grpc_logger grpc_logsettable.SettableLoggerV2 | ||||
| var insideTestContext bool | ||||
|  | ||||
| func init() { | ||||
| 	grpc_logger = grpc_logsettable.ReplaceGrpcLoggerV2() | ||||
| } | ||||
|  | ||||
| type testOptions struct { | ||||
| 	goLeakDetection bool | ||||
| 	skipInShort     bool | ||||
| } | ||||
|  | ||||
| func newTestOptions(opts ...TestOption) *testOptions { | ||||
| 	o := &testOptions{goLeakDetection: true, skipInShort: true} | ||||
| 	for _, opt := range opts { | ||||
| 		opt(o) | ||||
| 	} | ||||
| 	return o | ||||
| } | ||||
|  | ||||
| type TestOption func(opt *testOptions) | ||||
|  | ||||
| // WithoutGoLeakDetection disables checking whether a testcase leaked a goroutine. | ||||
| func WithoutGoLeakDetection() TestOption { | ||||
| 	return func(opt *testOptions) { opt.goLeakDetection = false } | ||||
| } | ||||
|  | ||||
| func WithoutSkipInShort() TestOption { | ||||
| 	return func(opt *testOptions) { opt.skipInShort = false } | ||||
| } | ||||
|  | ||||
| // BeforeTestExternal initializes test context and is targeted for external APIs. | ||||
| // In general the `integration` package is not targeted to be used outside of | ||||
| // etcd project, but till the dedicated package is developed, this is | ||||
| // the best entry point so far (without backward compatibility promise). | ||||
| func BeforeTestExternal(t testutil.TB) { | ||||
| 	BeforeTest(t, WithoutSkipInShort(), WithoutGoLeakDetection()) | ||||
| } | ||||
|  | ||||
| func BeforeTest(t testutil.TB, opts ...TestOption) { | ||||
| 	t.Helper() | ||||
| 	options := newTestOptions(opts...) | ||||
|  | ||||
| 	if options.skipInShort { | ||||
| 		testutil.SkipTestIfShortMode(t, "Cannot create clusters in --short tests") | ||||
| 	} | ||||
|  | ||||
| 	if options.goLeakDetection { | ||||
| 		testutil.RegisterLeakDetection(t) | ||||
| 	} | ||||
|  | ||||
| 	previousWD, err := os.Getwd() | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	previousInsideTestContext := insideTestContext | ||||
|  | ||||
| 	// Registering cleanup early, such it will get executed even if the helper fails. | ||||
| 	t.Cleanup(func() { | ||||
| 		grpc_logger.Reset() | ||||
| 		insideTestContext = previousInsideTestContext | ||||
| 		os.Chdir(previousWD) | ||||
| 	}) | ||||
|  | ||||
| 	if insideTestContext { | ||||
| 		t.Fatal("already in test context. BeforeTest was likely already called") | ||||
| 	} | ||||
|  | ||||
| 	grpc_logger.Set(zapgrpc.NewLogger(zaptest.NewLogger(t).Named("grpc"))) | ||||
| 	insideTestContext = true | ||||
|  | ||||
| 	// Integration tests should verify written state as much as possible. | ||||
| 	os.Setenv(verify.ENV_VERIFY, verify.ENV_VERIFY_ALL_VALUE) | ||||
| 	os.Chdir(t.TempDir()) | ||||
| } | ||||
|  | ||||
| func assertInTestContext(t testutil.TB) { | ||||
| 	if !insideTestContext { | ||||
| 		t.Errorf("the function can be called only in the test context. Was integration.BeforeTest() called ?") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func MustAbsPath(path string) string { | ||||
| 	abs, err := filepath.Abs(path) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return abs | ||||
| } | ||||
|  | ||||
| func NewEmbedConfig(t testing.TB, name string) *embed.Config { | ||||
| 	cfg := embed.NewConfig() | ||||
| 	cfg.Name = name | ||||
| 	lg := zaptest.NewLogger(t, zaptest.Level(zapcore.InfoLevel)).Named(cfg.Name) | ||||
| 	cfg.ZapLoggerBuilder = embed.NewZapLoggerBuilder(lg) | ||||
| 	cfg.Dir = t.TempDir() | ||||
| 	return cfg | ||||
| } | ||||
|  | ||||
| func NewClient(t testing.TB, cfg clientv3.Config) (*clientv3.Client, error) { | ||||
| 	if cfg.Logger != nil { | ||||
| 		cfg.Logger = zaptest.NewLogger(t) | ||||
| 	} | ||||
| 	return clientv3.New(cfg) | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							| @@ -467,7 +467,6 @@ github.com/gregjones/httpcache | ||||
| github.com/gregjones/httpcache/diskcache | ||||
| # github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 => github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 | ||||
| github.com/grpc-ecosystem/go-grpc-middleware | ||||
| github.com/grpc-ecosystem/go-grpc-middleware/logging/settable | ||||
| # github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 => github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 | ||||
| github.com/grpc-ecosystem/go-grpc-prometheus | ||||
| # github.com/grpc-ecosystem/grpc-gateway v1.16.0 => github.com/grpc-ecosystem/grpc-gateway v1.16.0 | ||||
| @@ -798,7 +797,6 @@ go.etcd.io/etcd/client/pkg/v3/logutil | ||||
| go.etcd.io/etcd/client/pkg/v3/pathutil | ||||
| go.etcd.io/etcd/client/pkg/v3/srv | ||||
| go.etcd.io/etcd/client/pkg/v3/systemd | ||||
| go.etcd.io/etcd/client/pkg/v3/testutil | ||||
| go.etcd.io/etcd/client/pkg/v3/tlsutil | ||||
| go.etcd.io/etcd/client/pkg/v3/transport | ||||
| go.etcd.io/etcd/client/pkg/v3/types | ||||
| @@ -811,9 +809,6 @@ go.etcd.io/etcd/client/v3/concurrency | ||||
| go.etcd.io/etcd/client/v3/credentials | ||||
| go.etcd.io/etcd/client/v3/internal/endpoint | ||||
| go.etcd.io/etcd/client/v3/internal/resolver | ||||
| go.etcd.io/etcd/client/v3/namespace | ||||
| go.etcd.io/etcd/client/v3/naming/endpoints | ||||
| go.etcd.io/etcd/client/v3/naming/endpoints/internal | ||||
| # go.etcd.io/etcd/pkg/v3 v3.5.0 => go.etcd.io/etcd/pkg/v3 v3.5.0 | ||||
| go.etcd.io/etcd/pkg/v3/adt | ||||
| go.etcd.io/etcd/pkg/v3/contention | ||||
| @@ -873,14 +868,10 @@ go.etcd.io/etcd/server/v3/lease/leasepb | ||||
| go.etcd.io/etcd/server/v3/mvcc | ||||
| go.etcd.io/etcd/server/v3/mvcc/backend | ||||
| go.etcd.io/etcd/server/v3/mvcc/buckets | ||||
| go.etcd.io/etcd/server/v3/proxy/grpcproxy | ||||
| go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter | ||||
| go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache | ||||
| go.etcd.io/etcd/server/v3/verify | ||||
| go.etcd.io/etcd/server/v3/wal | ||||
| go.etcd.io/etcd/server/v3/wal/walpb | ||||
| # go.etcd.io/etcd/tests/v3 v3.5.0 => go.etcd.io/etcd/tests/v3 v3.5.0 | ||||
| go.etcd.io/etcd/tests/v3/integration | ||||
| # go.opencensus.io v0.22.3 => go.opencensus.io v0.22.3 | ||||
| go.opencensus.io | ||||
| go.opencensus.io/internal | ||||
| @@ -1539,6 +1530,7 @@ k8s.io/apiserver/pkg/storage/errors | ||||
| k8s.io/apiserver/pkg/storage/etcd3 | ||||
| k8s.io/apiserver/pkg/storage/etcd3/metrics | ||||
| k8s.io/apiserver/pkg/storage/etcd3/testing | ||||
| k8s.io/apiserver/pkg/storage/etcd3/testserver | ||||
| k8s.io/apiserver/pkg/storage/names | ||||
| k8s.io/apiserver/pkg/storage/storagebackend | ||||
| k8s.io/apiserver/pkg/storage/storagebackend/factory | ||||
| @@ -2461,7 +2453,6 @@ sigs.k8s.io/yaml | ||||
| # github.com/emicklei/go-restful => github.com/emicklei/go-restful v2.9.5+incompatible | ||||
| # github.com/envoyproxy/go-control-plane => github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d | ||||
| # github.com/envoyproxy/protoc-gen-validate => github.com/envoyproxy/protoc-gen-validate v0.1.0 | ||||
| # github.com/etcd-io/gofail => github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca | ||||
| # github.com/euank/go-kmsg-parser => github.com/euank/go-kmsg-parser v2.0.0+incompatible | ||||
| # github.com/evanphx/json-patch => github.com/evanphx/json-patch v4.11.0+incompatible | ||||
| # github.com/exponent-io/jsonpath => github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d | ||||
| @@ -2563,7 +2554,7 @@ sigs.k8s.io/yaml | ||||
| # github.com/mailru/easyjson => github.com/mailru/easyjson v0.7.6 | ||||
| # github.com/mattn/go-colorable => github.com/mattn/go-colorable v0.0.9 | ||||
| # github.com/mattn/go-isatty => github.com/mattn/go-isatty v0.0.3 | ||||
| # github.com/mattn/go-runewidth => github.com/mattn/go-runewidth v0.0.9 | ||||
| # github.com/mattn/go-runewidth => github.com/mattn/go-runewidth v0.0.7 | ||||
| # github.com/matttproud/golang_protobuf_extensions => github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 | ||||
| # github.com/miekg/dns => github.com/miekg/dns v1.0.14 | ||||
| # github.com/mindprince/gonvml => github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 | ||||
| @@ -2591,7 +2582,7 @@ sigs.k8s.io/yaml | ||||
| # github.com/mxk/go-flowrate => github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f | ||||
| # github.com/niemeyer/pretty => github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e | ||||
| # github.com/nxadm/tail => github.com/nxadm/tail v1.4.4 | ||||
| # github.com/olekukonko/tablewriter => github.com/olekukonko/tablewriter v0.0.5 | ||||
| # github.com/olekukonko/tablewriter => github.com/olekukonko/tablewriter v0.0.4 | ||||
| # github.com/onsi/ginkgo => github.com/onsi/ginkgo v1.14.0 | ||||
| # github.com/onsi/gomega => github.com/onsi/gomega v1.10.1 | ||||
| # github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0 | ||||
| @@ -2655,11 +2646,9 @@ sigs.k8s.io/yaml | ||||
| # go.etcd.io/etcd/client/pkg/v3 => go.etcd.io/etcd/client/pkg/v3 v3.5.0 | ||||
| # go.etcd.io/etcd/client/v2 => go.etcd.io/etcd/client/v2 v2.305.0 | ||||
| # go.etcd.io/etcd/client/v3 => go.etcd.io/etcd/client/v3 v3.5.0 | ||||
| # go.etcd.io/etcd/etcdutl/v3 => go.etcd.io/etcd/etcdutl/v3 v3.5.0 | ||||
| # go.etcd.io/etcd/pkg/v3 => go.etcd.io/etcd/pkg/v3 v3.5.0 | ||||
| # go.etcd.io/etcd/raft/v3 => go.etcd.io/etcd/raft/v3 v3.5.0 | ||||
| # go.etcd.io/etcd/server/v3 => go.etcd.io/etcd/server/v3 v3.5.0 | ||||
| # go.etcd.io/etcd/tests/v3 => go.etcd.io/etcd/tests/v3 v3.5.0 | ||||
| # go.opencensus.io => go.opencensus.io v0.22.3 | ||||
| # go.opentelemetry.io/contrib => go.opentelemetry.io/contrib v0.20.0 | ||||
| # go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jordan Liggitt
					Jordan Liggitt