From 9df388112866985cb11994f0e64fda1516260f56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 13:26:55 +0000 Subject: [PATCH] build(deps): bump google.golang.org/grpc from 1.82.0 to 1.83.0 Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.82.0 to 1.83.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.82.0...v1.83.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.83.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 5 +- go.sum | 6 +- vendor/github.com/theckman/yacspin/.gitignore | 25 - .../theckman/yacspin/.golangci.yaml | 71 - vendor/github.com/theckman/yacspin/LICENSE | 201 --- vendor/github.com/theckman/yacspin/README.md | 274 ---- .../theckman/yacspin/character_sets.go | 121 -- vendor/github.com/theckman/yacspin/colors.go | 174 --- vendor/github.com/theckman/yacspin/spinner.go | 1191 ----------------- vendor/google.golang.org/grpc/clientconn.go | 23 +- .../clientconn_disconnect_reason_noplan9.go | 48 + .../clientconn_disconnect_reason_plan9.go | 39 + .../grpc/internal/envconfig/envconfig.go | 11 + .../grpc/internal/envconfig/xds.go | 7 +- .../internal/grpcsync/callback_serializer.go | 26 + .../grpc/internal/resolver/config_selector.go | 78 +- .../grpc/internal/transport/client_stream.go | 5 +- .../grpc/internal/transport/controlbuf.go | 174 ++- .../grpc/internal/transport/http2_client.go | 16 +- .../grpc/internal/transport/http2_server.go | 13 +- .../grpc/internal/transport/transport.go | 2 - vendor/google.golang.org/grpc/stream.go | 35 +- vendor/google.golang.org/grpc/version.go | 2 +- vendor/modules.txt | 5 +- 24 files changed, 265 insertions(+), 2287 deletions(-) delete mode 100644 vendor/github.com/theckman/yacspin/.gitignore delete mode 100644 vendor/github.com/theckman/yacspin/.golangci.yaml delete mode 100644 vendor/github.com/theckman/yacspin/LICENSE delete mode 100644 vendor/github.com/theckman/yacspin/README.md delete mode 100644 vendor/github.com/theckman/yacspin/character_sets.go delete mode 100644 vendor/github.com/theckman/yacspin/colors.go delete mode 100644 vendor/github.com/theckman/yacspin/spinner.go create mode 100644 vendor/google.golang.org/grpc/clientconn_disconnect_reason_noplan9.go create mode 100644 vendor/google.golang.org/grpc/clientconn_disconnect_reason_plan9.go diff --git a/go.mod b/go.mod index 9817bbc8e3..53f5f8a0ab 100644 --- a/go.mod +++ b/go.mod @@ -75,6 +75,7 @@ require ( github.com/rogpeppe/go-internal v1.15.0 github.com/rs/cors v1.11.1 github.com/rs/zerolog v1.35.1 + github.com/shamaton/msgpack/v2 v2.4.1 github.com/sirupsen/logrus v1.9.4 github.com/spf13/afero v1.15.0 github.com/spf13/cobra v1.10.2 @@ -84,7 +85,6 @@ require ( github.com/test-go/testify v1.1.4 github.com/testcontainers/testcontainers-go v0.43.0 github.com/testcontainers/testcontainers-go/modules/opensearch v0.43.0 - github.com/theckman/yacspin v0.13.12 github.com/thejerf/suture/v4 v4.0.6 github.com/tidwall/gjson v1.19.0 github.com/tidwall/sjson v1.2.5 @@ -111,7 +111,7 @@ require ( golang.org/x/term v0.45.0 golang.org/x/text v0.40.0 google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa - google.golang.org/grpc v1.82.0 + google.golang.org/grpc v1.83.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 @@ -344,7 +344,6 @@ require ( github.com/sergi/go-diff v1.4.0 // indirect github.com/sethvargo/go-diceware v0.5.0 // indirect github.com/sethvargo/go-password v0.3.1 // indirect - github.com/shamaton/msgpack/v2 v2.4.1 // indirect github.com/shirou/gopsutil/v4 v4.26.5 // indirect github.com/skeema/knownhosts v1.3.1 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect diff --git a/go.sum b/go.sum index daabd3d6b8..c026746fe3 100644 --- a/go.sum +++ b/go.sum @@ -1191,8 +1191,6 @@ github.com/testcontainers/testcontainers-go/modules/opensearch v0.43.0 h1:a1ipjF github.com/testcontainers/testcontainers-go/modules/opensearch v0.43.0/go.mod h1:OWSeUDiGMUy30iMsAltIJIo9uh/CleLv6KyxjYOsgR8= github.com/thanhpk/randstr v1.0.6 h1:psAOktJFD4vV9NEVb3qkhRSMvYh4ORRaj1+w/hn4B+o= github.com/thanhpk/randstr v1.0.6/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U= -github.com/theckman/yacspin v0.13.12 h1:CdZ57+n0U6JMuh2xqjnjRq5Haj6v1ner2djtLQRzJr4= -github.com/theckman/yacspin v0.13.12/go.mod h1:Rd2+oG2LmQi5f3zC3yeZAOl245z8QOvrH4OPOJNZxLg= github.com/thejerf/suture/v4 v4.0.6 h1:QsuCEsCqb03xF9tPAsWAj8QOAJBgQI1c0VqJNaingg8= github.com/thejerf/suture/v4 v4.0.6/go.mod h1:gu9Y4dXNUWFrByqRt30Rm9/UZ0wzRSt9AJS6xu/ZGxU= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -1722,8 +1720,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.82.0 h1:vguDnZUPjE26w09A63VoxZPnvPjB5Riyc0mkXPFmAIU= -google.golang.org/grpc v1.82.0/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA= +google.golang.org/grpc v1.83.0 h1:JeNZEKJFbQxArAMl+hiytHauacDNqJUllNfmIMmpqnQ= +google.golang.org/grpc v1.83.0/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e h1:m7aQHHqd0q89mRwhwS9Bx2rjyl/hsFAeta+uGrHsQaU= google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/vendor/github.com/theckman/yacspin/.gitignore b/vendor/github.com/theckman/yacspin/.gitignore deleted file mode 100644 index fa3fbdf514..0000000000 --- a/vendor/github.com/theckman/yacspin/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool -*.out -coverage.txt - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# README GIF generation files -*.mov -*.mp4 -*.gif -*.prproj - -# OS files -.DS_Store diff --git a/vendor/github.com/theckman/yacspin/.golangci.yaml b/vendor/github.com/theckman/yacspin/.golangci.yaml deleted file mode 100644 index 31b1123180..0000000000 --- a/vendor/github.com/theckman/yacspin/.golangci.yaml +++ /dev/null @@ -1,71 +0,0 @@ -run: - tests: true - -# all available settings of specific linters -linters-settings: - govet: - # report about shadowed variables - check-shadowing: true - gofmt: - # simplify code: gofmt with `-s` option, true by default - simplify: true - dupl: - # tokens count to trigger issue, 150 by default - threshold: 100 - goconst: - # minimal length of string constant, 3 by default - min-len: 3 - # minimal occurrences count to trigger, 3 by default - min-occurrences: 3 - misspell: - # Correct spellings using locale preferences for US or UK. - # Default is to use a neutral variety of English. - # Setting locale to US will correct the British spelling of 'colour' to 'color'. - locale: US - staticcheck: - checks: [ "all" ] - revive: - confidence: 0.8 - ignore-generated-header: true - rules: - - name: context-keys-type - - name: time-naming - - name: var-declaration - - name: unexported-return - - name: errorf - - name: blank-imports - - name: context-as-argument - - name: dot-imports - - name: error-return - - name: error-strings - - name: error-naming - - name: exported - - name: increment-decrement - - name: var-naming - - name: package-comments - - name: range - - name: receiver-naming - - name: indent-error-flow - - name: superfluous-else - - name: struct-tag - - name: modifies-value-receiver - - name: range-val-in-closure - - name: range-val-address - - name: atomic - - name: empty-lines - - name: early-return - - name: useless-break - -linters: - enable: - - revive - - govet - - gosec - - staticcheck - - typecheck - fast: false - -issues: - exclude-use-default: false - exclude: - - G104 diff --git a/vendor/github.com/theckman/yacspin/LICENSE b/vendor/github.com/theckman/yacspin/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/vendor/github.com/theckman/yacspin/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/theckman/yacspin/README.md b/vendor/github.com/theckman/yacspin/README.md deleted file mode 100644 index c7c21b1f02..0000000000 --- a/vendor/github.com/theckman/yacspin/README.md +++ /dev/null @@ -1,274 +0,0 @@ -# Yet Another CLi Spinner (for Go) -[![License](https://img.shields.io/github/license/theckman/yacspin.svg)](https://github.com/theckman/yacspin/blob/master/LICENSE) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/theckman/yacspin) -[![Latest Git Tag](https://img.shields.io/github/tag/theckman/yacspin.svg)](https://github.com/theckman/yacspin/releases) -[![GitHub Actions master Build Status](https://github.com/theckman/yacspin/actions/workflows/tests.yaml/badge.svg?branch=master)](https://github.com/theckman/yacspin/actions/workflows/tests.yaml) -[![Go Report Card](https://goreportcard.com/badge/github.com/theckman/yacspin)](https://goreportcard.com/report/github.com/theckman/yacspin) -[![Codecov](https://img.shields.io/codecov/c/github/theckman/yacspin)](https://codecov.io/gh/theckman/yacspin) - -Package `yacspin` provides yet another CLi spinner for Go, taking inspiration -(and some utility code) from the https://github.com/briandowns/spinner project. -Specifically `yacspin` borrows the default character sets, and color mappings to -github.com/fatih/color colors, from that project. - -## License -Because this package adopts the spinner character sets from https://github.com/briandowns/spinner, -this package is released under the Apache 2.0 License. - -## Yet Another CLi Spinner? -This project was created after it was realized that the most popular spinner -library for Go had some limitations, that couldn't be fixed without a massive -overhaul of the API. - -The other spinner ties the ability to show updated messages to the spinner's -animation, meaning you can't always show all the information you want to the end -user without changing the animation speed. This means you need to trade off -animation aesthetics to show "realtime" information. It was a goal to avoid this -problem. - -In addition, there were also some API design choices that have made it unsafe -for concurrent use, which presents challenges when trying to update the text in -the spinner while it's animating. This could result in undefined behavior due to -data races. - -There were also some variable-width spinners in that other project that did -not render correctly. Because the width of the spinner animation would change, -so would the position of the message on the screen. `yacspin` uses a dynamic -width when animating, so your message should appear static relative to the -animating spinner. - -Finally, there was an interest in the spinner being able to represent a task, and to -indicate whether it failed or was successful. This would have further compounded -the API changes needed above to support in an intuitive way. - -This project takes inspiration from that other project, and takes a new approach -to address the challenges above. - -## Features -#### Provided Spinners -There are over 90 spinners available in the `CharSets` package variable. They -were borrowed from [github.com/briandowns/spinner](https://github.com/briandowns/spinner). -There is a table with most of the spinners [at the bottom of this README](#Spinners). - -#### Dynamic Width of Animation -Because of how some spinners are animated, they may have different widths are -different times in the animation. `yacspin` calculates the maximum width, and -pads the animation to ensure the text's position on the screen doesn't change. -This results in a smoother looking animation. - -##### yacspin -![yacspin animation with dynamic width](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/features/width_good.gif) - -##### other spinners -![other spinners' animation with dynamic width](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/features/width_bad.gif) - -#### Success and Failure Results -The spinner has both a `Stop()` and `StopFail()` method, which allows the -spinner to result in a success message or a failure message. The messages, -colors, and even the character used to denote success or failure are -customizable in either the initial config or via the spinner's methods. - -By doing this you can use a single `yacspin` spinner to display the status of a -list of tasks being executed serially. - -##### Stop -![Animation with Success](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/features/stop.gif) - -##### StopFail -![Animation with Failure](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/features/stop_fail.gif) - -#### Animation At End of Line -The `SpinnerAtEnd` field of the `Config` struct allows you to specify whether -the spinner is rendered at the end of the line instead of the beginning. The -default value (`false`) results in the spinner being rendered at the beginning -of the line. - -#### Concurrency -The spinner is safe for concurrent use, so you can update any of its settings -via methods whether the spinner is stopped or is currently animating. - -#### Live Updates -Most spinners tie the ability to show new messages with the animation of the -spinner. So if the spinner animates every 200ms, you can only show updated -information every 200ms. If you wanted more frequent updates, you'd need to -tradeoff the asthetics of the animation to display more data. - -This spinner updates the printed information of the spinner immediately on -change, without the animation updating. This allows you to use an animation -speed that looks astheticaly pleasing, while also knowing the data presented to -the user will be updated live. - -You can see this in action in the following gif, where the filenames being -uploaded are rendered independent of the spinner being animated: - -![Animation with Success](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/features/stop.gif) - -#### Pausing for Updates -Sometimes you want to change a few settings, and don't want the spinner to -render your partially applied configuration. If your spinner is running, and you -want to change a few configuration items via method calls, you can `Pause()` the -spinner first. After making the changes you can call `Unpause()`, and it will -continue rendering like normal with the newly applied configuration. - -#### Supporting Non-Interactive (TTY) Output Targets -`yacspin` also has native support for non-interactive (TTY) output targets. By -default this is detected in the constructor, or can be overriden via the -`TerminalMode` `Config` struct field. When detecting the application is not -running withn a TTY session, the behavior of the spinner is different. - -Specifically, when this is automatically detected the spinner no longer uses -colors, disables the automatic spinner animation, and instead only animates the -spinner when updating the message. In addition, each animation is rendered on a -new line instead of overwriting the current line. - -This should result in human-readable output without any changes needed by -consumers, even when the system is writing to a non-TTY destination. - -#### Manually Stepping Animation -If you'd like to manually animate the spinner, you can do so by setting the -`TerminalMode` to `ForceNoTTYMode | ForceSmartTerminalMode`. In this mode the -spinner will still use colors and other text stylings, but the animation only -happens when data is updated and on individual lines. You can accomplish this by -calling the `Message()` method with the same used previously. - -## Usage -``` -go get github.com/theckman/yacspin -``` - -Within the `yacspin` package there are some default spinners stored in the -`yacspin.CharSets` variable, and you can also provide your own. There is also a -list of known colors in the `yacspin.ValidColors` variable. - -### Example - -There are runnable examples in the [examples/](https://github.com/theckman/yacspin/tree/master/examples) -directory, with one simple example and one more advanced one. Here is a quick -snippet showing usage from a very high level, with error handling omitted: - -```Go -cfg := yacspin.Config{ - Frequency: 100 * time.Millisecond, - CharSet: yacspin.CharSets[59], - Suffix: " backing up database to S3", - SuffixAutoColon: true, - Message: "exporting data", - StopCharacter: "✓", - StopColors: []string{"fgGreen"}, -} - -spinner, err := yacspin.New(cfg) -// handle the error - -err = spinner.Start() - -// doing some work -time.Sleep(2 * time.Second) - -spinner.Message("uploading data") - -// upload... -time.Sleep(2 * time.Second) - -err = spinner.Stop() -``` - -## Spinners - -The spinner animations below are recorded at a refresh frequency of 200ms. Some -animations may look better at a different speed, so play around with the -frequency until you find a value you find aesthetically pleasing. - -yacspin.CharSets index | sample gif (Frequency: 200ms) ------------------------|------------------------------ -0 | ![0 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/0.gif) -1 | ![1 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/1.gif) -2 | ![2 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/2.gif) -3 | ![3 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/3.gif) -4 | ![4 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/4.gif) -5 | ![5 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/5.gif) -6 | ![6 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/6.gif) -7 | ![7 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/7.gif) -8 | ![8 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/8.gif) -9 | ![9 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/9.gif) -10 | ![10 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/10.gif) -11 | ![11 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/11.gif) -12 | ![12 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/12.gif) -13 | ![13 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/13.gif) -14 | ![14 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/14.gif) -15 | ![15 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/15.gif) -16 | ![16 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/16.gif) -17 | ![17 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/17.gif) -18 | ![18 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/18.gif) -19 | ![19 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/19.gif) -20 | ![20 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/20.gif) -21 | ![21 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/21.gif) -22 | ![22 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/22.gif) -23 | ![23 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/23.gif) -24 | ![24 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/24.gif) -25 | ![25 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/25.gif) -26 | ![26 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/26.gif) -27 | ![27 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/27.gif) -28 | ![28 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/28.gif) -29 | ![29 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/29.gif) -30 | ![30 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/30.gif) -31 | ![31 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/31.gif) -32 | ![32 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/32.gif) -33 | ![33 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/33.gif) -34 | ![34 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/34.gif) -35 | ![35 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/35.gif) -36 | ![36 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/36.gif) -37 | ![37 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/37.gif) -38 | ![38 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/38.gif) -39 | ![39 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/39.gif) -40 | ![40 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/40.gif) -41 | ![41 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/41.gif) -42 | ![42 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/42.gif) -43 | ![43 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/43.gif) -44 | ![44 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/44.gif) -45 | ![45 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/45.gif) -46 | ![46 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/46.gif) -47 | ![47 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/47.gif) -48 | ![48 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/48.gif) -49 | ![49 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/49.gif) -50 | ![50 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/50.gif) -51 | ![51 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/51.gif) -52 | ![52 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/52.gif) -53 | ![53 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/53.gif) -54 | ![54 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/54.gif) -55 | ![55 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/55.gif) -56 | ![56 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/56.gif) -57 | ![57 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/57.gif) -58 | ![58 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/58.gif) -59 | ![59 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/59.gif) -60 | ![60 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/60.gif) -61 | ![61 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/61.gif) -62 | ![62 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/62.gif) -63 | ![63 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/63.gif) -64 | ![64 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/64.gif) -65 | ![65 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/65.gif) -66 | ![66 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/66.gif) -67 | ![67 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/67.gif) -68 | ![68 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/68.gif) -69 | ![69 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/69.gif) -70 | ![70 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/70.gif) -71 | ![71 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/71.gif) -72 | ![72 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/72.gif) -73 | ![73 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/73.gif) -74 | ![74 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/74.gif) -75 | ![75 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/75.gif) -76 | ![76 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/76.gif) -77 | ![77 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/77.gif) -78 | ![78 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/78.gif) -79 | ![79 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/79.gif) -80 | ![80 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/80.gif) -81 | ![81 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/81.gif) -82 | ![82 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/82.gif) -83 | ![83 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/83.gif) -84 | ![84 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/84.gif) -85 | ![85 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/85.gif) -86 | ![86 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/86.gif) -87 | ![87 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/87.gif) -88 | ![88 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/88.gif) -89 | ![89 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/89.gif) -90 | ![90 gif](https://raw.githubusercontent.com/theckman/yacspin-gifs/11953a4f12560eaf4a27054d3adad471eb19193c/spinners/90.gif) diff --git a/vendor/github.com/theckman/yacspin/character_sets.go b/vendor/github.com/theckman/yacspin/character_sets.go deleted file mode 100644 index 7fb5990f7f..0000000000 --- a/vendor/github.com/theckman/yacspin/character_sets.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2021 Brian J. Downs -// Copyright (c) 2019-2021 Tim Heckman -// -// 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. -// -// Please see the LICENSE file for the copy of the Apache 2.0 License. -// -// This file was copied from: https://github.com/briandowns/spinner -// -// Modifications: -// -// - removed runtime generation of CharSets 37 and 38; made them literals -// - fixed pipe spinner (32) animation, by adding missing frame - -package yacspin - -// CharSets contains the default character sets from -// https://github.com/briandowns/spinner. -var CharSets = map[int][]string{ - 0: {"←", "↖", "↑", "↗", "→", "↘", "↓", "↙"}, - 1: {"▁", "▃", "▄", "▅", "▆", "▇", "█", "▇", "▆", "▅", "▄", "▃", "▁"}, - 2: {"▖", "▘", "▝", "▗"}, - 3: {"┤", "┘", "┴", "└", "├", "┌", "┬", "┐"}, - 4: {"◢", "◣", "◤", "◥"}, - 5: {"◰", "◳", "◲", "◱"}, - 6: {"◴", "◷", "◶", "◵"}, - 7: {"◐", "◓", "◑", "◒"}, - 8: {".", "o", "O", "@", "*"}, - 9: {"|", "/", "-", "\\"}, - 10: {"◡◡", "⊙⊙", "◠◠"}, - 11: {"⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"}, - 12: {">))'>", " >))'>", " >))'>", " >))'>", " >))'>", " <'((<", " <'((<", " <'((<"}, - 13: {"⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"}, - 14: {"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}, - 15: {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}, - 16: {"▉", "▊", "▋", "▌", "▍", "▎", "▏", "▎", "▍", "▌", "▋", "▊", "▉"}, - 17: {"■", "□", "▪", "▫"}, - 18: {"←", "↑", "→", "↓"}, - 19: {"╫", "╪"}, - 20: {"⇐", "⇖", "⇑", "⇗", "⇒", "⇘", "⇓", "⇙"}, - 21: {"⠁", "⠁", "⠉", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠤", "⠄", "⠄", "⠤", "⠠", "⠠", "⠤", "⠦", "⠖", "⠒", "⠐", "⠐", "⠒", "⠓", "⠋", "⠉", "⠈", "⠈"}, - 22: {"⠈", "⠉", "⠋", "⠓", "⠒", "⠐", "⠐", "⠒", "⠖", "⠦", "⠤", "⠠", "⠠", "⠤", "⠦", "⠖", "⠒", "⠐", "⠐", "⠒", "⠓", "⠋", "⠉", "⠈"}, - 23: {"⠁", "⠉", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠤", "⠄", "⠄", "⠤", "⠴", "⠲", "⠒", "⠂", "⠂", "⠒", "⠚", "⠙", "⠉", "⠁"}, - 24: {"⠋", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠦", "⠖", "⠒", "⠐", "⠐", "⠒", "⠓", "⠋"}, - 25: {"ヲ", "ァ", "ィ", "ゥ", "ェ", "ォ", "ャ", "ュ", "ョ", "ッ", "ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ヤ", "ユ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ン"}, - 26: {".", "..", "..."}, - 27: {"▁", "▂", "▃", "▄", "▅", "▆", "▇", "█", "▉", "▊", "▋", "▌", "▍", "▎", "▏", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█", "▇", "▆", "▅", "▄", "▃", "▂", "▁"}, - 28: {".", "o", "O", "°", "O", "o", "."}, - 29: {"+", "x"}, - 30: {"v", "<", "^", ">"}, - 31: {">>--->", " >>--->", " >>--->", " >>--->", " >>--->", " <---<<", " <---<<", " <---<<", " <---<<", "<---<<"}, - 32: {"|", "||", "|||", "||||", "|||||", "||||||", "|||||||", "||||||||", "|||||||", "||||||", "|||||", "||||", "|||", "||", "|"}, - 33: {"[ ]", "[= ]", "[== ]", "[=== ]", "[==== ]", "[===== ]", "[====== ]", "[======= ]", "[======== ]", "[========= ]", "[==========]"}, - 34: {"(*---------)", "(-*--------)", "(--*-------)", "(---*------)", "(----*-----)", "(-----*----)", "(------*---)", "(-------*--)", "(--------*-)", "(---------*)"}, - 35: {"█▒▒▒▒▒▒▒▒▒", "███▒▒▒▒▒▒▒", "█████▒▒▒▒▒", "███████▒▒▒", "██████████"}, - 36: {"[ ]", "[=> ]", "[===> ]", "[=====> ]", "[======> ]", "[========> ]", "[==========> ]", "[============> ]", "[==============> ]", "[================> ]", "[==================> ]", "[===================>]"}, - 37: {"🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", "🕛"}, // clock emoji: one per hour for hours 1~12 - 38: {"🕐", "🕜", "🕑", "🕝", "🕒", "🕞", "🕓", "🕟", "🕔", "🕠", "🕕", "🕡", "🕖", "🕢", "🕗", "🕣", "🕘", "🕤", "🕙", "🕥", "🕚", "🕦", "🕛", "🕧"}, // clock emoji: one per half hour for hours 1~12 - 39: {"🌍", "🌎", "🌏"}, - 40: {"◜", "◝", "◞", "◟"}, - 41: {"⬒", "⬔", "⬓", "⬕"}, - 42: {"⬖", "⬘", "⬗", "⬙"}, - 43: {"[>>> >]", "[]>>>> []", "[] >>>> []", "[] >>>> []", "[] >>>> []", "[] >>>>[]", "[>> >>]"}, - 44: {"♠", "♣", "♥", "♦"}, - 45: {"➞", "➟", "➠", "➡", "➠", "➟"}, - 46: {" | ", ` \ `, "_ ", ` \ `, " | ", " / ", " _", " / "}, - 47: {" . . . .", ". . . .", ". . . .", ". . . .", ". . . . ", ". . . . ."}, - 48: {" | ", " / ", " _ ", ` \ `, " | ", ` \ `, " _ ", " / "}, - 49: {"⎺", "⎻", "⎼", "⎽", "⎼", "⎻"}, - 50: {"▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸"}, - 51: {"[ ]", "[ =]", "[ ==]", "[ ===]", "[====]", "[=== ]", "[== ]", "[= ]"}, - 52: {"( ● )", "( ● )", "( ● )", "( ● )", "( ●)", "( ● )", "( ● )", "( ● )", "( ● )"}, - 53: {"✶", "✸", "✹", "✺", "✹", "✷"}, - 54: {"▐|\\____________▌", "▐_|\\___________▌", "▐__|\\__________▌", "▐___|\\_________▌", "▐____|\\________▌", "▐_____|\\_______▌", "▐______|\\______▌", "▐_______|\\_____▌", "▐________|\\____▌", "▐_________|\\___▌", "▐__________|\\__▌", "▐___________|\\_▌", "▐____________|\\▌", "▐____________/|▌", "▐___________/|_▌", "▐__________/|__▌", "▐_________/|___▌", "▐________/|____▌", "▐_______/|_____▌", "▐______/|______▌", "▐_____/|_______▌", "▐____/|________▌", "▐___/|_________▌", "▐__/|__________▌", "▐_/|___________▌", "▐/|____________▌"}, - 55: {"▐⠂ ▌", "▐⠈ ▌", "▐ ⠂ ▌", "▐ ⠠ ▌", "▐ ⡀ ▌", "▐ ⠠ ▌", "▐ ⠂ ▌", "▐ ⠈ ▌", "▐ ⠂ ▌", "▐ ⠠ ▌", "▐ ⡀ ▌", "▐ ⠠ ▌", "▐ ⠂ ▌", "▐ ⠈ ▌", "▐ ⠂▌", "▐ ⠠▌", "▐ ⡀▌", "▐ ⠠ ▌", "▐ ⠂ ▌", "▐ ⠈ ▌", "▐ ⠂ ▌", "▐ ⠠ ▌", "▐ ⡀ ▌", "▐ ⠠ ▌", "▐ ⠂ ▌", "▐ ⠈ ▌", "▐ ⠂ ▌", "▐ ⠠ ▌", "▐ ⡀ ▌", "▐⠠ ▌"}, - 56: {"¿", "?"}, - 57: {"⢹", "⢺", "⢼", "⣸", "⣇", "⡧", "⡗", "⡏"}, - 58: {"⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠"}, - 59: {". ", ".. ", "...", " ..", " .", " "}, - 60: {".", "o", "O", "°", "O", "o", "."}, - 61: {"▓", "▒", "░"}, - 62: {"▌", "▀", "▐", "▄"}, - 63: {"⊶", "⊷"}, - 64: {"▪", "▫"}, - 65: {"□", "■"}, - 66: {"▮", "▯"}, - 67: {"-", "=", "≡"}, - 68: {"d", "q", "p", "b"}, - 69: {"∙∙∙", "●∙∙", "∙●∙", "∙∙●", "∙∙∙"}, - 70: {"🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "}, - 71: {"☗", "☖"}, - 72: {"⧇", "⧆"}, - 73: {"◉", "◎"}, - 74: {"㊂", "㊀", "㊁"}, - 75: {"⦾", "⦿"}, - 76: {"ဝ", "၀"}, - 77: {"▌", "▀", "▐▄"}, - 78: {"⠈⠁", "⠈⠑", "⠈⠱", "⠈⡱", "⢀⡱", "⢄⡱", "⢄⡱", "⢆⡱", "⢎⡱", "⢎⡰", "⢎⡠", "⢎⡀", "⢎⠁", "⠎⠁", "⠊⠁"}, - 79: {"________", "-_______", "_-______", "__-_____", "___-____", "____-___", "_____-__", "______-_", "_______-", "________", "_______-", "______-_", "_____-__", "____-___", "___-____", "__-_____", "_-______", "-_______", "________"}, - 80: {"|_______", "_/______", "__-_____", "___\\____", "____|___", "_____/__", "______-_", "_______\\", "_______|", "______\\_", "_____-__", "____/___", "___|____", "__\\_____", "_-______"}, - 81: {"□", "◱", "◧", "▣", "■"}, - 82: {"□", "◱", "▨", "▩", "■"}, - 83: {"░", "▒", "▓", "█"}, - 84: {"░", "█"}, - 85: {"⚪", "⚫"}, - 86: {"◯", "⬤"}, - 87: {"▱", "▰"}, - 88: {"➊", "➋", "➌", "➍", "➎", "➏", "➐", "➑", "➒", "➓"}, - 89: {"½", "⅓", "⅔", "¼", "¾", "⅛", "⅜", "⅝", "⅞"}, - 90: {"↞", "↟", "↠", "↡"}, -} diff --git a/vendor/github.com/theckman/yacspin/colors.go b/vendor/github.com/theckman/yacspin/colors.go deleted file mode 100644 index 1a0bc8a620..0000000000 --- a/vendor/github.com/theckman/yacspin/colors.go +++ /dev/null @@ -1,174 +0,0 @@ -// This file is available under the Apache 2.0 License -// This file was copied from: https://github.com/briandowns/spinner -// -// Please see the LICENSE file for the copy of the Apache 2.0 License. -// -// Modifications: -// -// - made validColors set map more idiomatic with an empty struct value -// - added a function for creating color functions from color list - -package yacspin - -import ( - "fmt" - - "github.com/fatih/color" -) - -// ValidColors holds the list of the strings that are mapped to -// github.com/fatih/color color attributes. Any of these colors / attributes can -// be used with the *Spinner type, and it should be reflected in the output. -var ValidColors = map[string]struct{}{ - // default colors for backwards compatibility - "black": {}, - "red": {}, - "green": {}, - "yellow": {}, - "blue": {}, - "magenta": {}, - "cyan": {}, - "white": {}, - - // attributes - "reset": {}, - "bold": {}, - "faint": {}, - "italic": {}, - "underline": {}, - "blinkslow": {}, - "blinkrapid": {}, - "reversevideo": {}, - "concealed": {}, - "crossedout": {}, - - // foreground text - "fgBlack": {}, - "fgRed": {}, - "fgGreen": {}, - "fgYellow": {}, - "fgBlue": {}, - "fgMagenta": {}, - "fgCyan": {}, - "fgWhite": {}, - - // foreground Hi-Intensity text - "fgHiBlack": {}, - "fgHiRed": {}, - "fgHiGreen": {}, - "fgHiYellow": {}, - "fgHiBlue": {}, - "fgHiMagenta": {}, - "fgHiCyan": {}, - "fgHiWhite": {}, - - // background text - "bgBlack": {}, - "bgRed": {}, - "bgGreen": {}, - "bgYellow": {}, - "bgBlue": {}, - "bgMagenta": {}, - "bgCyan": {}, - "bgWhite": {}, - - // background Hi-Intensity text - "bgHiBlack": {}, - "bgHiRed": {}, - "bgHiGreen": {}, - "bgHiYellow": {}, - "bgHiBlue": {}, - "bgHiMagenta": {}, - "bgHiCyan": {}, - "bgHiWhite": {}, -} - -// returns a valid color's foreground text color attribute -var colorAttributeMap = map[string]color.Attribute{ - // default colors for backwards compatibility - "black": color.FgBlack, - "red": color.FgRed, - "green": color.FgGreen, - "yellow": color.FgYellow, - "blue": color.FgBlue, - "magenta": color.FgMagenta, - "cyan": color.FgCyan, - "white": color.FgWhite, - - // attributes - "reset": color.Reset, - "bold": color.Bold, - "faint": color.Faint, - "italic": color.Italic, - "underline": color.Underline, - "blinkslow": color.BlinkSlow, - "blinkrapid": color.BlinkRapid, - "reversevideo": color.ReverseVideo, - "concealed": color.Concealed, - "crossedout": color.CrossedOut, - - // foreground text colors - "fgBlack": color.FgBlack, - "fgRed": color.FgRed, - "fgGreen": color.FgGreen, - "fgYellow": color.FgYellow, - "fgBlue": color.FgBlue, - "fgMagenta": color.FgMagenta, - "fgCyan": color.FgCyan, - "fgWhite": color.FgWhite, - - // foreground Hi-Intensity text colors - "fgHiBlack": color.FgHiBlack, - "fgHiRed": color.FgHiRed, - "fgHiGreen": color.FgHiGreen, - "fgHiYellow": color.FgHiYellow, - "fgHiBlue": color.FgHiBlue, - "fgHiMagenta": color.FgHiMagenta, - "fgHiCyan": color.FgHiCyan, - "fgHiWhite": color.FgHiWhite, - - // background text colors - "bgBlack": color.BgBlack, - "bgRed": color.BgRed, - "bgGreen": color.BgGreen, - "bgYellow": color.BgYellow, - "bgBlue": color.BgBlue, - "bgMagenta": color.BgMagenta, - "bgCyan": color.BgCyan, - "bgWhite": color.BgWhite, - - // background Hi-Intensity text colors - "bgHiBlack": color.BgHiBlack, - "bgHiRed": color.BgHiRed, - "bgHiGreen": color.BgHiGreen, - "bgHiYellow": color.BgHiYellow, - "bgHiBlue": color.BgHiBlue, - "bgHiMagenta": color.BgHiMagenta, - "bgHiCyan": color.BgHiCyan, - "bgHiWhite": color.BgHiWhite, -} - -// validColor will make sure the given color is actually allowed -func validColor(c string) bool { - _, ok := ValidColors[c] - - return ok -} - -func colorFunc(colors ...string) (func(format string, a ...interface{}) string, error) { - if len(colors) == 0 { - return fmt.Sprintf, nil - } - - attrib := make([]color.Attribute, len(colors)) - - for i, color := range colors { - if !validColor(color) { - return nil, fmt.Errorf("%s is not a valid color", color) - } - - attrib[i] = colorAttributeMap[color] - } - - return color.New(attrib...).SprintfFunc(), nil -} diff --git a/vendor/github.com/theckman/yacspin/spinner.go b/vendor/github.com/theckman/yacspin/spinner.go deleted file mode 100644 index dd96e5f3fa..0000000000 --- a/vendor/github.com/theckman/yacspin/spinner.go +++ /dev/null @@ -1,1191 +0,0 @@ -// Package yacspin provides Yet Another CLi Spinner for Go, taking inspiration -// (and some utility code) from the https://github.com/briandowns/spinner -// project. Specifically this project borrows the default character sets, and -// color mappings to github.com/fatih/color colors, from that project. -// -// This spinner should support all major operating systems, and is tested -// against Linux, MacOS, and Windows. -// -// This spinner also supports an alternate mode of operation when the TERM -// environment variable is set to "dumb". This is discovered automatically when -// constructing the spinner. -// -// Within the yacspin package there are some default spinners stored in the -// yacspin.CharSets variable, and you can also provide your own. There is also a -// list of known colors in the yacspin.ValidColors variable, if you'd like to -// see what's supported. If you've used github.com/fatih/color before, they -// should look familiar. -// -// cfg := yacspin.Config{ -// Frequency: 100 * time.Millisecond, -// CharSet: yacspin.CharSets[59], -// Suffix: " backing up database to S3", -// Message: "exporting data", -// StopCharacter: "✓", -// StopColors: []string{"fgGreen"}, -// } -// -// spinner, err := yacspin.New(cfg) -// // handle the error -// -// spinner.Start() -// -// // doing some work -// time.Sleep(2 * time.Second) -// -// spinner.Message("uploading data") -// -// // upload... -// time.Sleep(2 * time.Second) -// -// spinner.Stop() -// -// Check out the Config struct to see all of the possible configuration options -// supported by the Spinner. -package yacspin - -import ( - "bytes" - "errors" - "fmt" - "io" - "math" - "os" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/mattn/go-colorable" - "github.com/mattn/go-isatty" - "github.com/mattn/go-runewidth" -) - -type character struct { - Value string - Size int -} - -func setToCharSlice(ss []string) ([]character, int) { - if len(ss) == 0 { - return nil, 0 - } - - var maxWidth int - c := make([]character, len(ss)) - - for i, s := range ss { - n := runewidth.StringWidth(s) - if n > maxWidth { - maxWidth = n - } - - c[i] = character{ - Value: s, - Size: n, - } - } - - return c, maxWidth -} - -// TerminalMode is a type to represent the bit flag controlling the terminal -// mode of the spinner, accepted as a field on the Config struct. See the -// comments on the exported constants for more info. -type TerminalMode uint32 - -const ( - // AutomaticMode configures the constructor function to try and determine if - // the application using yacspin is being executed within a interactive - // (teletype [TTY]) session. - AutomaticMode TerminalMode = 1 << iota - - // ForceTTYMode configures the spinner to operate as if it's running within - // a TTY session. - ForceTTYMode - - // ForceNoTTYMode configures the spinner to operate as if it's not running - // within a TTY session. This mode causes the spinner to only animate when - // data is being updated. Each animation is rendered on a new line. You can - // trigger an animation by calling the Message() method, including with the - // last value it was called with. - ForceNoTTYMode - - // ForceDumbTerminalMode configures the spinner to operate as if it's - // running within a dumb terminal. This means the spinner will not use ANSI - // escape sequences to print colors or to erase each line. Line erasure to - // animate the spinner is accomplished by overwriting the line with space - // characters. - ForceDumbTerminalMode - - // ForceSmartTerminalMode configures the spinner to operate as if it's - // running within a terminal that supports ANSI escape sequences (VT100). - // This includes printing of stylized text, and more better line erasure to - // animate the spinner. - ForceSmartTerminalMode -) - -func termModeAuto(t TerminalMode) bool { return t&AutomaticMode > 0 } -func termModeForceTTY(t TerminalMode) bool { return t&ForceTTYMode > 0 } -func termModeForceNoTTY(t TerminalMode) bool { return t&ForceNoTTYMode > 0 } -func termModeForceDumb(t TerminalMode) bool { return t&ForceDumbTerminalMode > 0 } -func termModeForceSmart(t TerminalMode) bool { return t&ForceSmartTerminalMode > 0 } - -// Config is the configuration structure for the Spinner type, which you provide -// to the New() function. Some of the fields can be updated after the *Spinner -// is constructed, others can only be set when calling the constructor. Please -// read the comments for those details. -type Config struct { - // Frequency specifies how often to animate the spinner. Optimal value - // depends on the character set you use. - Frequency time.Duration - - // Writer is the place where we are outputting the spinner, and can't be - // changed after the *Spinner has been constructed. If omitted (nil), this - // defaults to os.Stdout. - Writer io.Writer - - // ShowCursor specifies that the cursor should be shown by the spinner while - // animating. If it is not shown, the cursor will be restored when the - // spinner stops. This can't be changed after the *Spinner has been - // constructed. - // - // Please note, if you do not set this to true and the program crashes or is - // killed, you may need to reset your terminal for the cursor to appear - // again. - ShowCursor bool - - // HideCursor describes whether the cursor should be hidden by the spinner - // while animating. If it is hidden, it will be restored when the spinner - // stops. This can't be changed after the *Spinner has been constructed. - // - // Please note, if the program crashes or is killed you may need to reset - // your terminal for the cursor to appear again. - // - // Deprecated: use ShowCursor instead. - HideCursor bool - - // SpinnerAtEnd configures the spinner to render the animation at the end of - // the line instead of the beginning. The default behavior is to render the - // animated spinner at the beginning of the line. - SpinnerAtEnd bool - - // ColorAll describes whether to color everything (all) or just the spinner - // character(s). This cannot be changed after the *Spinner has been - // constructed. - ColorAll bool - - // Colors are the colors used for the different printed messages. This - // respects the ColorAll field. - Colors []string - - // CharSet is the list of characters to iterate through to draw the spinner. - CharSet []string - - // Prefix is the string printed immediately before the spinner. - // - // If SpinnerAtEnd is set to true, it's recommended that this string start - // with a space character (` `). - Prefix string - - // Suffix is the string printed immediately after the spinner and before the - // message. - // - // If SpinnerAtEnd is set to false, it's recommended that this string starts - // with an space character (` `). - Suffix string - - // SuffixAutoColon configures whether the spinner adds a colon after the - // suffix automatically. If there is a message, a colon followed by a space - // is added to the suffix. Otherwise, if there is no message, or the suffix - // is only space characters, the colon is omitted. - // - // If SpinnerAtEnd is set to true, this option is ignored. - SuffixAutoColon bool - - // Message is the message string printed by the spinner. If SpinnerAtEnd is - // set to false and SuffixAutoColon is set to true, the printed line will - // look like: - // - // : - // - // If SpinnerAtEnd is set to true, the printed line will instead look like - // this: - // - // - // - // In this case, it may be preferred to set the Prefix to empty space (` `). - Message string - - // StopMessage is the message used when Stop() is called. - StopMessage string - - // StopCharacter is spinner character used when Stop() is called. - // Recommended character is ✓, and can be more than just one character. - StopCharacter string - - // StopColors are the colors used for the Stop() printed line. This respects - // the ColorAll field. - StopColors []string - - // StopFailMessage is the message used when StopFail() is called. - StopFailMessage string - - // StopFailCharacter is the spinner character used when StopFail() is - // called. Recommended character is ✗, and can be more than just one - // character. - StopFailCharacter string - - // StopFailColors are the colors used for the StopFail() printed line. This - // respects the ColorAll field. - StopFailColors []string - - // TerminalMode is a bitflag field to control how the internal TTY / "dumb - // terminal" detection works, to allow consumers to override the internal - // behaviors. To set this value, it's recommended to use the TerminalMode - // constants exported by this package. - // - // If not set, the New() function implicitly sets it to AutomaticMode. The - // New() function also returns an error if you have conflicting flags, such - // as setting ForceTTYMode and ForceNoTTYMode, or if you set AutomaticMode - // and any other flags set. - // - // When in AutomaticMode, the New() function attempts to determine if the - // current application is running within an interactive (teletype [TTY]) - // session. If it does not appear to be within a TTY, it sets this field - // value to ForceNoTTYMode | ForceDumbTerminalMode. - // - // If this does appear to be a TTY, the ForceTTYMode bitflag will bet set. - // Similarly, if it's a TTY and the TERM environment variable isn't set to - // "dumb" the ForceSmartTerminalMode bitflag will also be set. - // - // If the deprecated NoTTY Config struct field is set to true, and this - // field is AutomaticMode, the New() function sets field to the value of - // ForceNoTTYMode | ForceDumbTerminalMode. - TerminalMode TerminalMode - - // NotTTY tells the spinner that the Writer should not be treated as a TTY. - // This results in the animation being disabled, with the animation only - // happening whenever the data is updated. This mode also renders each - // update on new line, versus reusing the current line. - // - // Deprecated: use TerminalMode field instead by setting it to: - // ForceNoTTYMode | ForceDumbTerminalMode. This will be removed in a future - // release. - NotTTY bool -} - -// Spinner is a type representing an animated CLi terminal spinner. The Spinner -// is constructed by the New() function of this package, which accepts a Config -// struct as the only argument. Some of the configuration values cannot be -// changed after the spinner is constructed, so be sure to read the comments -// within the Config type. -// -// Please note, by default the spinner will hide the terminal cursor when -// animating the spinner. If you do not set Config.ShowCursor to true, you need -// to make sure to call the Stop() or StopFail() method to reset the cursor in -// the terminal. Otherwise, after the program exits the cursor will be hidden -// and the user will need to `reset` their terminal. -type Spinner struct { - writer io.Writer - buffer *bytes.Buffer - colorAll bool - cursorHidden bool - suffixAutoColon bool - termMode TerminalMode - spinnerAtEnd bool - - status *uint32 - lastPrintLen int - cancelCh chan struct{} // send: Stop(), close: StopFail(); both stop painter - doneCh chan struct{} - pauseCh chan struct{} - unpauseCh chan struct{} - unpausedCh chan struct{} - - // mutex hat and the fields wearing it - mu *sync.Mutex - frequency time.Duration - chars []character - maxWidth int - index int - prefix string - suffix string - message string - colorFn func(format string, a ...interface{}) string - stopMsg string - stopChar character - stopColorFn func(format string, a ...interface{}) string - stopFailMsg string - stopFailChar character - stopFailColorFn func(format string, a ...interface{}) string - frequencyUpdateCh chan time.Duration - dataUpdateCh chan struct{} -} - -const ( - statusStopped uint32 = iota - statusStarting - statusRunning - statusStopping - statusPausing - statusPaused - statusUnpausing -) - -// New creates a new unstarted spinner. If stdout does not appear to be a TTY, -// this constructor implicitly sets cfg.NotTTY to true. -func New(cfg Config) (*Spinner, error) { - if cfg.ShowCursor && cfg.HideCursor { - return nil, errors.New("cfg.ShowCursor and cfg.HideCursor cannot be true") - } - - if cfg.TerminalMode == 0 { - cfg.TerminalMode = AutomaticMode - } - - // AutomaticMode flag has been set, but so have others - if termModeAuto(cfg.TerminalMode) && cfg.TerminalMode != AutomaticMode { - return nil, errors.New("cfg.TerminalMode cannot have AutomaticMode flag set if others are set") - } - - if termModeForceTTY(cfg.TerminalMode) && termModeForceNoTTY(cfg.TerminalMode) { - return nil, errors.New("cfg.TerminalMode cannot have both ForceTTYMode and ForceNoTTYMode flags set") - } - - if termModeForceDumb(cfg.TerminalMode) && termModeForceSmart(cfg.TerminalMode) { - return nil, errors.New("cfg.TerminalMode cannot have both ForceDumbTerminalMode and ForceSmartTerminalMode flags set") - } - - if cfg.HideCursor { - cfg.ShowCursor = false - } - - // cfg.NotTTY compatibility - if cfg.TerminalMode == AutomaticMode && cfg.NotTTY { - cfg.TerminalMode = ForceNoTTYMode | ForceDumbTerminalMode - } - - // is this a dumb terminal / not a TTY? - if cfg.TerminalMode == AutomaticMode && !isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()) { - cfg.TerminalMode = ForceNoTTYMode | ForceDumbTerminalMode - } - - // if cfg.TerminalMode is still equal to AutomaticMode, this is a TTY - if cfg.TerminalMode == AutomaticMode { - cfg.TerminalMode = ForceTTYMode - - if os.Getenv("TERM") == "dumb" { - cfg.TerminalMode |= ForceDumbTerminalMode - } else { - cfg.TerminalMode |= ForceSmartTerminalMode - } - } - - buf := bytes.NewBuffer(make([]byte, 2048)) - buf.Reset() - - s := &Spinner{ - buffer: buf, - mu: &sync.Mutex{}, - frequency: cfg.Frequency, - status: uint32Ptr(0), - frequencyUpdateCh: make(chan time.Duration), // use unbuffered for now to avoid .Frequency() panic - dataUpdateCh: make(chan struct{}), - - colorAll: cfg.ColorAll, - cursorHidden: !cfg.ShowCursor, - spinnerAtEnd: cfg.SpinnerAtEnd, - suffixAutoColon: cfg.SuffixAutoColon, - termMode: cfg.TerminalMode, - colorFn: fmt.Sprintf, - stopColorFn: fmt.Sprintf, - stopFailColorFn: fmt.Sprintf, - } - - if err := s.Colors(cfg.Colors...); err != nil { - return nil, err - } - - if err := s.StopColors(cfg.StopColors...); err != nil { - return nil, err - } - - if err := s.StopFailColors(cfg.StopFailColors...); err != nil { - return nil, err - } - - if len(cfg.CharSet) == 0 { - cfg.CharSet = CharSets[9] - } - - // can only error if the charset is empty, and we prevent that above - _ = s.CharSet(cfg.CharSet) - - if termModeForceNoTTY(s.termMode) { - // hack to prevent the animation from running if not a TTY - s.frequency = time.Duration(math.MaxInt64) - } - - if cfg.Writer == nil { - cfg.Writer = colorable.NewColorableStdout() - } - - s.writer = cfg.Writer - - if len(cfg.Prefix) > 0 { - s.Prefix(cfg.Prefix) - } - - if len(cfg.Suffix) > 0 { - s.Suffix(cfg.Suffix) - } - - if len(cfg.Message) > 0 { - s.Message(cfg.Message) - } - - if len(cfg.StopMessage) > 0 { - s.StopMessage(cfg.StopMessage) - } - - if len(cfg.StopCharacter) > 0 { - s.StopCharacter(cfg.StopCharacter) - } - - if len(cfg.StopFailMessage) > 0 { - s.StopFailMessage(cfg.StopFailMessage) - } - - if len(cfg.StopFailCharacter) > 0 { - s.StopFailCharacter(cfg.StopFailCharacter) - } - - return s, nil -} - -func (s *Spinner) notifyDataChange() { - // non-blocking notification - select { - case s.dataUpdateCh <- struct{}{}: - default: - } -} - -// SpinnerStatus describes the status of the spinner. See the package constants -// for the list of all possible statuses -type SpinnerStatus uint32 - -const ( - // SpinnerStopped is a stopped spinner - SpinnerStopped SpinnerStatus = iota - - // SpinnerStarting is a starting spinner - SpinnerStarting - - // SpinnerRunning is a running spinner - SpinnerRunning - - // SpinnerStopping is a stopping spinner - SpinnerStopping - - // SpinnerPausing is a pausing spinner - SpinnerPausing - - // SpinnerPaused is a paused spinner - SpinnerPaused - - // SpinnerUnpausing is an unpausing spinner - SpinnerUnpausing -) - -func (s SpinnerStatus) String() string { - switch s { - case SpinnerStopped: - return "stopped" - case SpinnerStarting: - return "starting" - case SpinnerRunning: - return "running" - case SpinnerStopping: - return "stopping" - case SpinnerPausing: - return "pausing" - case SpinnerPaused: - return "paused" - case SpinnerUnpausing: - return "unpausing" - default: - return fmt.Sprintf("unknown (%d)", s) - } -} - -// Status returns the current status of the spinner. The returned value is of -// type SpinnerStatus, which can be compared against the exported Spinner* -// package-level constants (e.g., SpinnerRunning). -func (s *Spinner) Status() SpinnerStatus { - return SpinnerStatus(atomic.LoadUint32(s.status)) -} - -// Start begins the spinner on the Writer in the Config provided to New(). Only -// possible error is if the spinner is already runninng. -func (s *Spinner) Start() error { - // move us to the starting state - if !atomic.CompareAndSwapUint32(s.status, statusStopped, statusStarting) { - return errors.New("spinner already running or shutting down") - } - - // we now have atomic guarantees of no other goroutines starting or running - - s.mu.Lock() - - if s.frequency < 1 && termModeForceTTY(s.termMode) { - return errors.New("spinner Frequency duration must be greater than 0 when used within a TTY") - } - - if len(s.chars) == 0 { - s.mu.Unlock() - - // move us to the stopped state - if !atomic.CompareAndSwapUint32(s.status, statusStarting, statusStopped) { - panic("atomic invariant encountered") - } - - return errors.New("before starting the spinner a CharSet must be set") - } - - s.frequencyUpdateCh = make(chan time.Duration, 4) - s.dataUpdateCh, s.cancelCh = make(chan struct{}, 1), make(chan struct{}, 1) - - s.mu.Unlock() - - // because of the atomic swap above, we know it's safe to mutate these - // values outside of mutex - s.doneCh = make(chan struct{}) - s.pauseCh = make(chan struct{}) // unbuffered since we want this to be synchronous - - go s.painter(s.cancelCh, s.dataUpdateCh, s.pauseCh, s.doneCh, s.frequencyUpdateCh) - - // move us to the running state - if !atomic.CompareAndSwapUint32(s.status, statusStarting, statusRunning) { - panic("atomic invariant encountered") - } - - return nil -} - -// Pause puts the spinner in a state where it no longer animates or renders -// updates to data. This function blocks until the spinner's internal painting -// goroutine enters a paused state. -// -// If you want to make a few configuration changes and have them to appear at -// the same time, like changing the suffix, message, and color, you can Pause() -// the spinner first and then Unpause() after making the changes. -// -// If the spinner is not running (stopped, paused, or in transition to another -// state) this returns an error. -func (s *Spinner) Pause() error { - if !atomic.CompareAndSwapUint32(s.status, statusRunning, statusPausing) { - return errors.New("spinner not running") - } - - // set up the channels the painter will use - s.unpauseCh, s.unpausedCh = make(chan struct{}), make(chan struct{}) - - // inform the painter to pause as a blocking send - s.pauseCh <- struct{}{} - - if !atomic.CompareAndSwapUint32(s.status, statusPausing, statusPaused) { - panic("atomic invariant encountered") - } - - return nil -} - -// Unpause returns the spinner back to a running state after pausing. See -// Pause() documentation for more detail. This function blocks until the -// spinner's internal painting goroutine acknowledges the request to unpause. -// -// If the spinner is not paused this returns an error. -func (s *Spinner) Unpause() error { - if !atomic.CompareAndSwapUint32(s.status, statusPaused, statusUnpausing) { - return errors.New("spinner not paused") - } - - s.unpause() - - if !atomic.CompareAndSwapUint32(s.status, statusUnpausing, statusRunning) { - panic("atomic invariant encountered") - } - - return nil -} - -func (s *Spinner) unpause() { - // tell the painter to unpause - close(s.unpauseCh) - - // wait for the painter to signal it will continue - <-s.unpausedCh - - // clear the no longer needed channels - s.unpauseCh = nil - s.unpausedCh = nil -} - -// Stop disables the spinner, and prints the StopCharacter with the StopMessage -// using the StopColors. This blocks until the stopped message is printed. Only -// possible error is if the spinner is not running. -func (s *Spinner) Stop() error { - return s.stop(false) -} - -// StopFail disables the spinner, and prints the StopFailCharacter with the -// StopFailMessage using the StopFailColors. This blocks until the stopped -// message is printed. Only possible error is if the spinner is not running. -func (s *Spinner) StopFail() error { - return s.stop(true) -} - -func (s *Spinner) stop(fail bool) error { - // move us to a stopping state to protect against concurrent Stop() calls - wasRunning := atomic.CompareAndSwapUint32(s.status, statusRunning, statusStopping) - wasPaused := atomic.CompareAndSwapUint32(s.status, statusPaused, statusStopping) - - if !wasRunning && !wasPaused { - return errors.New("spinner not running or paused") - } - - // we now have an atomic guarantees of no other threads invoking state changes - - if !fail { - // this tells the painter to print the StopMessage and not the - // StopFailMessage - s.cancelCh <- struct{}{} - } - - close(s.cancelCh) - - if wasPaused { - s.unpause() - } - - // wait for the painter to stop - <-s.doneCh - - s.mu.Lock() - - s.dataUpdateCh = make(chan struct{}) // prevent panic() in various setter methods - s.frequencyUpdateCh = make(chan time.Duration) // prevent panic() in .Frequency() - - s.mu.Unlock() - - // because of atomic swaps and channel receive above we know it's - // safe to mutate these fields outside of the mutex - s.index = 0 - s.cancelCh = nil - s.doneCh = nil - s.pauseCh = nil - - // move us to the stopped state - if !atomic.CompareAndSwapUint32(s.status, statusStopping, statusStopped) { - panic("atomic invariant encountered") - } - - return nil -} - -// handleFrequencyUpdate is for when the frequency was changed. This tries to -// see if we should fire the timer now, or change its current duration to match -// the new duration. -func handleFrequencyUpdate(newFrequency time.Duration, timer *time.Timer, lastTick time.Time) { - // if timer fired, drain the channel - if !timer.Stop() { - timerLoop: - for { - select { - case <-timer.C: - default: - break timerLoop - } - } - } - - timeSince := time.Since(lastTick) - - // if we've exceeded the new delay trigger timer immediately - if timeSince >= newFrequency { - timer.Reset(0) - return - } - - timer.Reset(newFrequency - timeSince) -} - -func (s *Spinner) painter(cancel, dataUpdate, pause <-chan struct{}, done chan<- struct{}, frequencyUpdate <-chan time.Duration) { - timer := time.NewTimer(0) - var lastTick time.Time - - for { - select { - case <-timer.C: - lastTick = time.Now() - - s.paintUpdate(timer, true) - - case <-pause: - <-s.unpauseCh - close(s.unpausedCh) - - case <-dataUpdate: - // if this is not a TTY: animate the spinner on the data update - s.paintUpdate(timer, termModeForceNoTTY(s.termMode)) - - case frequency := <-frequencyUpdate: - handleFrequencyUpdate(frequency, timer, lastTick) - - case _, ok := <-cancel: - defer close(done) - - timer.Stop() - - s.paintStop(ok) - - return - } - } -} - -func (s *Spinner) paintUpdate(timer *time.Timer, animate bool) { - s.mu.Lock() - - p := s.prefix - m := s.message - suf := s.suffix - mw := s.maxWidth - cFn := s.colorFn - d := s.frequency - index := s.index - - if animate { - s.index++ - - if s.index == len(s.chars) { - s.index = 0 - } - } else { - // for data updates use the last spinner char - index-- - - if index < 0 { - index = len(s.chars) - 1 - } - } - - c := s.chars[index] - - s.mu.Unlock() - - defer s.buffer.Reset() - - if termModeForceSmart(s.termMode) { - if err := erase(s.buffer); err != nil { - panic(fmt.Sprintf("failed to erase line: %v", err)) - } - - if s.cursorHidden { - if err := hideCursor(s.buffer); err != nil { - panic(fmt.Sprintf("failed to hide cursor: %v", err)) - } - } - - if _, err := paint(s.buffer, mw, c, p, m, suf, s.suffixAutoColon, s.colorAll, s.spinnerAtEnd, false, termModeForceNoTTY(s.termMode), cFn); err != nil { - panic(fmt.Sprintf("failed to paint line: %v", err)) - } - } else { - if err := s.eraseDumbTerm(s.buffer); err != nil { - panic(fmt.Sprintf("failed to erase line: %v", err)) - } - - n, err := paint(s.buffer, mw, c, p, m, suf, s.suffixAutoColon, false, s.spinnerAtEnd, false, termModeForceNoTTY(s.termMode), fmt.Sprintf) - if err != nil { - panic(fmt.Sprintf("failed to paint line: %v", err)) - } - - s.lastPrintLen = n - } - - if s.buffer.Len() > 0 { - if _, err := s.writer.Write(s.buffer.Bytes()); err != nil { - panic(fmt.Sprintf("failed to output buffer to writer: %v", err)) - } - } - - if animate { - timer.Reset(d) - } -} - -func (s *Spinner) paintStop(chanOk bool) { - var m string - var c character - var cFn func(format string, a ...interface{}) string - - s.mu.Lock() - - if chanOk { - c = s.stopChar - cFn = s.stopColorFn - m = s.stopMsg - } else { - c = s.stopFailChar - cFn = s.stopFailColorFn - m = s.stopFailMsg - } - - p := s.prefix - suf := s.suffix - mw := s.maxWidth - - s.mu.Unlock() - - defer s.buffer.Reset() - - if termModeForceSmart(s.termMode) { - if err := erase(s.buffer); err != nil { - panic(fmt.Sprintf("failed to erase line: %v", err)) - } - - if s.cursorHidden { - if err := unhideCursor(s.buffer); err != nil { - panic(fmt.Sprintf("failed to hide cursor: %v", err)) - } - } - - if c.Size > 0 || len(m) > 0 { - // paint the line with a newline as it's the final line - if _, err := paint(s.buffer, mw, c, p, m, suf, s.suffixAutoColon, s.colorAll, s.spinnerAtEnd, true, termModeForceNoTTY(s.termMode), cFn); err != nil { - panic(fmt.Sprintf("failed to paint line: %v", err)) - } - } - } else { - if err := s.eraseDumbTerm(s.buffer); err != nil { - panic(fmt.Sprintf("failed to erase line: %v", err)) - } - - if c.Size > 0 || len(m) > 0 { - if _, err := paint(s.buffer, mw, c, p, m, suf, s.suffixAutoColon, false, s.spinnerAtEnd, true, termModeForceNoTTY(s.termMode), fmt.Sprintf); err != nil { - panic(fmt.Sprintf("failed to paint line: %v", err)) - } - } - - s.lastPrintLen = 0 - } - - if s.buffer.Len() > 0 { - if _, err := s.writer.Write(s.buffer.Bytes()); err != nil { - panic(fmt.Sprintf("failed to output buffer to writer: %v", err)) - } - } -} - -// erase clears the line -func erase(w io.Writer) error { - _, err := fmt.Fprint(w, "\r\033[K\r") - return err -} - -// eraseDumbTerm clears the line on dumb terminals -func (s *Spinner) eraseDumbTerm(w io.Writer) error { - if termModeForceNoTTY(s.termMode) { - // non-TTY outputs use \n instead of line erasure, - // so return early - return nil - } - - clear := "\r" + strings.Repeat(" ", s.lastPrintLen) + "\r" - - _, err := fmt.Fprint(w, clear) - return err -} - -func hideCursor(w io.Writer) error { - _, err := fmt.Fprint(w, "\r\033[?25l\r") - return err -} - -func unhideCursor(w io.Writer) error { - _, err := fmt.Fprint(w, "\r\033[?25h\r") - return err -} - -// padChar pads the spinner character so suffix / message offset from left is -// consistent -func padChar(char character, maxWidth int) string { - padSize := maxWidth - char.Size - return char.Value + strings.Repeat(" ", padSize) -} - -// paint writes a single line to the w, using the provided character, message, -// and color function -func paint(w io.Writer, maxWidth int, char character, prefix, message, suffix string, suffixAutoColon, colorAll, spinnerAtEnd, finalPaint, notTTY bool, colorFn func(format string, a ...interface{}) string) (int, error) { - var output string - - switch char.Size { - case 0: - if colorAll { - output = colorFn(message) - break - } - - output = message - - default: - c := padChar(char, maxWidth) - - if spinnerAtEnd { - if colorAll { - output = colorFn("%s%s%s%s", message, prefix, c, suffix) - break - } - - output = fmt.Sprintf("%s%s%s%s", message, prefix, colorFn(c), suffix) - break - } - - if suffixAutoColon { // also implicitly !spinnerAtEnd - if len(strings.TrimSpace(suffix)) > 0 && len(message) > 0 && message != "\n" { - suffix += ": " - } - } - - if colorAll { - output = colorFn("%s%s%s%s", prefix, c, suffix, message) - break - } - - output = fmt.Sprintf("%s%s%s%s", prefix, colorFn(c), suffix, message) - } - - if finalPaint || notTTY { - output += "\n" - } - - return fmt.Fprint(w, output) -} - -// Frequency updates the frequency of the spinner being animated. -func (s *Spinner) Frequency(d time.Duration) error { - if d < 1 { - return errors.New("duration must be greater than 0") - } - - if termModeForceNoTTY(s.termMode) { - // when output target is not a TTY, we don't animate spinner - // so there is no need to update the frequency - return nil - } - - s.mu.Lock() - defer s.mu.Unlock() - - s.frequency = d - - // non-blocking notification - select { - case s.frequencyUpdateCh <- d: - default: - } - - return nil -} - -// Prefix updates the Prefix before the spinner character. -func (s *Spinner) Prefix(prefix string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.prefix = prefix - - s.notifyDataChange() -} - -// Suffix updates the Suffix printed after the spinner character and before the -// message. It's recommended that this start with an empty space. -func (s *Spinner) Suffix(suffix string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.suffix = suffix - - s.notifyDataChange() -} - -// Message updates the Message displayed after the suffix. -func (s *Spinner) Message(message string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.message = message - - s.notifyDataChange() -} - -// Colors updates the github.com/fatih/colors for printing the spinner line. -// ColorAll config parameter controls whether only the spinner character is -// printed with these colors, or the whole line. -// -// StopColors() is the method to control the colors in the stop message. -func (s *Spinner) Colors(colors ...string) error { - colorFn, err := colorFunc(colors...) - if err != nil { - return fmt.Errorf("failed to build color function: %w", err) - } - - s.mu.Lock() - defer s.mu.Unlock() - - s.colorFn = colorFn - - s.notifyDataChange() - - return nil -} - -// StopMessage updates the Message used when Stop() is called. -func (s *Spinner) StopMessage(message string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.stopMsg = message - - s.notifyDataChange() -} - -// StopColors updates the colors used for the stop message. See Colors() method -// documentation for more context. -// -// StopFailColors() is the method to control the colors in the failed stop -// message. -func (s *Spinner) StopColors(colors ...string) error { - colorFn, err := colorFunc(colors...) - if err != nil { - return fmt.Errorf("failed to build stop color function: %w", err) - } - - s.mu.Lock() - defer s.mu.Unlock() - - s.stopColorFn = colorFn - - s.notifyDataChange() - - return nil -} - -// StopCharacter sets the single "character" to use for the spinner when -// stopping. Recommended character is ✓. -func (s *Spinner) StopCharacter(char string) { - n := runewidth.StringWidth(char) - - s.mu.Lock() - defer s.mu.Unlock() - - s.stopChar = character{Value: char, Size: n} - - if n > s.maxWidth { - s.maxWidth = n - } - - s.notifyDataChange() -} - -// StopFailMessage updates the Message used when StopFail() is called. -func (s *Spinner) StopFailMessage(message string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.stopFailMsg = message - - s.notifyDataChange() -} - -// StopFailColors updates the colors used for the StopFail message. See Colors() method -// documentation for more context. -func (s *Spinner) StopFailColors(colors ...string) error { - colorFn, err := colorFunc(colors...) - if err != nil { - return fmt.Errorf("failed to build stop fail color function: %w", err) - } - - s.mu.Lock() - defer s.mu.Unlock() - - s.stopFailColorFn = colorFn - - s.notifyDataChange() - - return nil -} - -// StopFailCharacter sets the single "character" to use for the spinner when -// stopping for a failure. Recommended character is ✗. -func (s *Spinner) StopFailCharacter(char string) { - n := runewidth.StringWidth(char) - - s.mu.Lock() - defer s.mu.Unlock() - - s.stopFailChar = character{Value: char, Size: n} - - if n > s.maxWidth { - s.maxWidth = n - } - - s.notifyDataChange() -} - -// CharSet updates the set of characters (strings) to use for the spinner. You -// can provide your own, or use one from the yacspin.CharSets variable. -// -// The character sets available in the CharSets variable are from the -// https://github.com/briandowns/spinner project. -func (s *Spinner) CharSet(cs []string) error { - if len(cs) == 0 { - return errors.New("failed to set character set: must provide at least one string") - } - - chars, mw := setToCharSlice(cs) - s.mu.Lock() - defer s.mu.Unlock() - - if n := s.stopChar.Size; n > mw { - mw = s.stopChar.Size - } - - if n := s.stopFailChar.Size; n > mw { - mw = n - } - - s.chars = chars - s.maxWidth = mw - s.index = 0 - - return nil -} - -// Reverse flips the character set order of the spinner characters. -func (s *Spinner) Reverse() { - s.mu.Lock() - defer s.mu.Unlock() - - for i, j := 0, len(s.chars)-1; i < j; { - s.chars[i], s.chars[j] = s.chars[j], s.chars[i] - i++ - j-- - } - - s.index = 0 -} - -func uint32Ptr(u uint32) *uint32 { return &u } diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go index c4bca5203e..b27c7e84a3 100644 --- a/vendor/google.golang.org/grpc/clientconn.go +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -24,12 +24,10 @@ import ( "fmt" "math" "net/url" - "os" "slices" "strings" "sync" "sync/atomic" - "syscall" "time" "google.golang.org/grpc/balancer" @@ -1573,26 +1571,13 @@ func (ac *addrConn) createTransport(ctx context.Context, addr resolver.Address, // to the provided transport.GoAwayInfo, as specified by gRFC A94: // https://github.com/grpc/proposal/blob/master/A94-grpc-subchannel-disconnections-metrics.md func disconnectErrorString(info transport.GoAwayInfo) string { - err := info.Err - var sysErr syscall.Errno - switch { - case info.Reason != transport.GoAwayInvalid: + if info.Reason != transport.GoAwayInvalid { return fmt.Sprintf("GOAWAY %s", info.GoAwayCode.String()) - case err == nil: - return "unknown" - case errors.Is(err, context.Canceled): - return "subchannel shutdown" - case errors.Is(err, syscall.ECONNRESET): - return "connection reset" - case errors.Is(err, syscall.ETIMEDOUT), errors.Is(err, context.DeadlineExceeded), errors.Is(err, os.ErrDeadlineExceeded): - return "connection timed out" - case errors.Is(err, syscall.ECONNABORTED): - return "connection aborted" - case errors.As(err, &sysErr): - return "socket error" - default: + } + if info.Err == nil { return "unknown" } + return disconnectErrorLabel(info.Err) } // startHealthCheck starts the health checking stream (RPC) to watch the health diff --git a/vendor/google.golang.org/grpc/clientconn_disconnect_reason_noplan9.go b/vendor/google.golang.org/grpc/clientconn_disconnect_reason_noplan9.go new file mode 100644 index 0000000000..f0fcd88423 --- /dev/null +++ b/vendor/google.golang.org/grpc/clientconn_disconnect_reason_noplan9.go @@ -0,0 +1,48 @@ +//go:build !plan9 + +/* + * + * Copyright 2026 gRPC 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 grpc + +import ( + "context" + "errors" + "os" + "syscall" +) + +// disconnectErrorLabel returns the grpc.disconnect_error metric label for a +// transport error, as specified by gRFC A94. +func disconnectErrorLabel(err error) string { + var sysErr syscall.Errno + switch { + case errors.Is(err, context.Canceled): + return "subchannel shutdown" + case errors.Is(err, syscall.ECONNRESET): + return "connection reset" + case errors.Is(err, syscall.ETIMEDOUT), errors.Is(err, context.DeadlineExceeded), errors.Is(err, os.ErrDeadlineExceeded): + return "connection timed out" + case errors.Is(err, syscall.ECONNABORTED): + return "connection aborted" + case errors.As(err, &sysErr): + return "socket error" + default: + return "unknown" + } +} diff --git a/vendor/google.golang.org/grpc/clientconn_disconnect_reason_plan9.go b/vendor/google.golang.org/grpc/clientconn_disconnect_reason_plan9.go new file mode 100644 index 0000000000..930b12664c --- /dev/null +++ b/vendor/google.golang.org/grpc/clientconn_disconnect_reason_plan9.go @@ -0,0 +1,39 @@ +/* + * + * Copyright 2026 gRPC 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 grpc + +import ( + "context" + "errors" + "os" +) + +// disconnectErrorLabel returns the grpc.disconnect_error metric label for a +// transport error, as specified by gRFC A94. syscall.Errno does not exist on +// plan9, so only the portable classifications are available. +func disconnectErrorLabel(err error) string { + switch { + case errors.Is(err, context.Canceled): + return "subchannel shutdown" + case errors.Is(err, context.DeadlineExceeded), errors.Is(err, os.ErrDeadlineExceeded): + return "connection timed out" + default: + return "unknown" + } +} diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go index ba05b65d5b..29d332e7b6 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go @@ -141,6 +141,17 @@ var ( // feature if unforeseen issues arise, and it will be removed in a future // release. EnableHTTPFramerReadBufferPooling = boolFromEnv("GRPC_GO_EXPERIMENTAL_HTTP_FRAMER_READ_BUFFER_POOLING", true) + + // ControlBufferThrottleLimit is the maximum number of control frames that can + // be queued in the control buffer before throttling is applied. The value + // must be between 1 and 10,000, and is set to 100 by default. + // + // This environment variable serves as an escape hatch to increase the + // throttling limit if unforeseen issues arise, and it will be removed in a + // future release. + // + // TODO: Remove this env var once v1.83.0 is release. + ControlBufferThrottleLimit = uint64FromEnv("GRPC_GO_EXPERIMENTAL_CONTROL_BUFFER_THROTTLE_LIMIT", 100, 1, 10000) ) func boolFromEnv(envVar string, def bool) bool { diff --git a/vendor/google.golang.org/grpc/internal/envconfig/xds.go b/vendor/google.golang.org/grpc/internal/envconfig/xds.go index a2312f8eac..e4b6919138 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/xds.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/xds.go @@ -69,9 +69,8 @@ var ( // https://github.com/grpc/proposal/blob/master/A87-mtls-spiffe-support.md XDSSPIFFEEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_MTLS_SPIFFE", false) - // XDSHTTPConnectEnabled is true if gRPC should parse custom Metadata - // configuring use of an HTTP CONNECT proxy via xDS from cluster resources. - // For more details, see: + // XDSHTTPConnectEnabled controls support for dynamic HTTP CONNECT proxying + // configured via the xDS control plane. For more details, see: // https://github.com/grpc/proposal/blob/master/A86-xds-http-connect.md XDSHTTPConnectEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_HTTP_CONNECT", false) @@ -88,7 +87,7 @@ var ( // XDSORCAToLRSPropEnabled controls whether ORCA metrics are explicitly // filtered and prefix-propagated to the LRS server. For more details, see: // https://github.com/grpc/proposal/blob/master/A85-lrs-custom-metrics-changes.md - XDSORCAToLRSPropEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_ORCA_LRS_PROPAGATION", false) + XDSORCAToLRSPropEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_ORCA_LRS_PROPAGATION", true) // XDSClientExtProcEnabled indicates whether ExtProc filter is enabled on // the client side. For more details, see: diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go b/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go index 9b6d8a1fa3..d4999fcca8 100644 --- a/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go +++ b/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go @@ -20,10 +20,15 @@ package grpcsync import ( "context" + "errors" "google.golang.org/grpc/internal/buffer" ) +// ErrSerializerClosed is returned by ScheduleAndWait if the CallbackSerializer +// was closed before the callback could be scheduled. +var ErrSerializerClosed = errors.New("callback serializer is closed") + // CallbackSerializer provides a mechanism to schedule callbacks in a // synchronized manner. It provides a FIFO guarantee on the order of execution // of scheduled callbacks. New callbacks can be scheduled by invoking the @@ -77,6 +82,27 @@ func (cs *CallbackSerializer) ScheduleOr(f func(ctx context.Context), onFailure } } +// ScheduleAndWait schedules the provided callback function f to be executed in +// the order it was added and blocks until f has run. If the context passed to +// NewCallbackSerializer was canceled before this method is called, f is not run +// and ScheduleAndWait returns ErrSerializerClosed. +// +// Callbacks are expected to honor the context when performing any blocking +// operations, and should return early when the context is canceled. +func (cs *CallbackSerializer) ScheduleAndWait(f func(ctx context.Context)) error { + done := make(chan struct{}) + var err error + cs.ScheduleOr(func(ctx context.Context) { + f(ctx) + close(done) + }, func() { + err = ErrSerializerClosed + close(done) + }) + <-done + return err +} + func (cs *CallbackSerializer) run(ctx context.Context) { defer close(cs.done) diff --git a/vendor/google.golang.org/grpc/internal/resolver/config_selector.go b/vendor/google.golang.org/grpc/internal/resolver/config_selector.go index 6320e9b576..238950bbbf 100644 --- a/vendor/google.golang.org/grpc/internal/resolver/config_selector.go +++ b/vendor/google.golang.org/grpc/internal/resolver/config_selector.go @@ -24,7 +24,6 @@ import ( "sync" "google.golang.org/grpc/internal/serviceconfig" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/resolver" ) @@ -52,82 +51,7 @@ type RPCConfig struct { Context context.Context MethodConfig serviceconfig.MethodConfig // configuration to use for this RPC OnCommitted func() // Called when the RPC has been committed (retries no longer possible) - Interceptor ClientInterceptor -} - -// ClientStream is the same as grpc.ClientStream, but defined here for circular -// dependency reasons. -type ClientStream interface { - // Header returns the header metadata received from the server if there - // is any. It blocks if the metadata is not ready to read. - Header() (metadata.MD, error) - // Trailer returns the trailer metadata from the server, if there is any. - // It must only be called after stream.CloseAndRecv has returned, or - // stream.Recv has returned a non-nil error (including io.EOF). - Trailer() metadata.MD - // CloseSend closes the send direction of the stream. It closes the stream - // when non-nil error is met. It is also not safe to call CloseSend - // concurrently with SendMsg. - CloseSend() error - // Context returns the context for this stream. - // - // It should not be called until after Header or RecvMsg has returned. Once - // called, subsequent client-side retries are disabled. - Context() context.Context - // SendMsg is generally called by generated code. On error, SendMsg aborts - // the stream. If the error was generated by the client, the status is - // returned directly; otherwise, io.EOF is returned and the status of - // the stream may be discovered using RecvMsg. - // - // SendMsg blocks until: - // - There is sufficient flow control to schedule m with the transport, or - // - The stream is done, or - // - The stream breaks. - // - // SendMsg does not wait until the message is received by the server. An - // untimely stream closure may result in lost messages. To ensure delivery, - // users should ensure the RPC completed successfully using RecvMsg. - // - // It is safe to have a goroutine calling SendMsg and another goroutine - // calling RecvMsg on the same stream at the same time, but it is not safe - // to call SendMsg on the same stream in different goroutines. It is also - // not safe to call CloseSend concurrently with SendMsg. - SendMsg(m any) error - // RecvMsg blocks until it receives a message into m or the stream is - // done. It returns io.EOF when the stream completes successfully. On - // any other error, the stream is aborted and the error contains the RPC - // status. - // - // It is safe to have a goroutine calling SendMsg and another goroutine - // calling RecvMsg on the same stream at the same time, but it is not - // safe to call RecvMsg on the same stream in different goroutines. - RecvMsg(m any) error -} - -// ClientInterceptor is an interceptor for gRPC client streams. -type ClientInterceptor interface { - // NewStream creates a ClientStream for an RPC. - // - // Implementations must delegate stream creation to the provided newStream - // function. To intercept or override stream behavior, implementations - // may wrap the ClientStream returned by the delegate. - // - // Note: RPCInfo.Context is currently unused and will be nil. - // - // The done function is invoked when the RPC has finished using its - // underlying connection or if a connection could not be assigned. Because - // interceptors operate at the application layer, RPC operations may - // continue on the ClientStream even after done has been called. The - // caller must ensure done is non-nil. - // - // To ensure RPC completion notifications propagate through the entire - // interceptor chain, implementations must ensure that the done function - // passed to the delegate newStream invokes the done function passed to - // NewStream. - NewStream(ctx context.Context, ri RPCInfo, done func(), newStream func(ctx context.Context, done func()) (ClientStream, error)) (ClientStream, error) - // Close closes the interceptor. Once called, no new calls to NewStream are - // accepted. Ongoing calls to NewStream are allowed to complete. - Close() + Interceptor any } // ServerInterceptor is an interceptor for incoming RPC's on gRPC server side. diff --git a/vendor/google.golang.org/grpc/internal/transport/client_stream.go b/vendor/google.golang.org/grpc/internal/transport/client_stream.go index ad382b0fda..046f0a5557 100644 --- a/vendor/google.golang.org/grpc/internal/transport/client_stream.go +++ b/vendor/google.golang.org/grpc/internal/transport/client_stream.go @@ -39,9 +39,8 @@ const nonGRPCDataMaxLen = 1024 type ClientStream struct { Stream // Embed for common stream functionality. - ct *http2Client - done chan struct{} // closed at the end of stream to unblock writers. - doneFunc func() // invoked at the end of stream. + ct *http2Client + done chan struct{} // closed at the end of stream to unblock writers. headerChan chan struct{} // closed to indicate the end of header metadata. header metadata.MD // the received header metadata diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go index c5a76b70ad..b9bae02498 100644 --- a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go +++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go @@ -29,6 +29,7 @@ import ( "golang.org/x/net/http2" "golang.org/x/net/http2/hpack" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/mem" ) @@ -96,61 +97,70 @@ func (il *itemList) isEmpty() bool { return il.head == nil } +// maxQueuedControlBufferItems is the maximum number of frames (other than +// HEADERS and DATA) that we will buffer before preventing new reads from +// occurring on the transport. These are control frames sent in response to +// client requests, or frames that result in work being scheduled, such as +// RST_STREAM due to bad headers or settings acks. +var maxQueuedControlBufferItems = int(envconfig.ControlBufferThrottleLimit) + +type cbItem interface { + isThrottled() bool +} + +// throttledItem represents every item in the controlBuffer to which the overall +// throttling limit applies, other than outgoing HEADERS and DATA frames. +type throttledItem struct{} + +func (throttledItem) isThrottled() bool { return true } + // The following defines various control items which could flow through // the control buffer of transport. They represent different aspects of // control tasks, e.g., flow control, settings, streaming resetting, etc. -// maxQueuedTransportResponseFrames is the most queued "transport response" -// frames we will buffer before preventing new reads from occurring on the -// transport. These are control frames sent in response to client requests, -// such as RST_STREAM due to bad headers or settings acks. -const maxQueuedTransportResponseFrames = 50 - -type cbItem interface { - isTransportResponseFrame() bool -} - // registerStream is used to register an incoming stream with loopy writer. type registerStream struct { + throttledItem streamID uint32 wq *writeQuota } -func (*registerStream) isTransportResponseFrame() bool { return false } - -// headerFrame is also used to register stream on the client-side. -type headerFrame struct { +type clientHeaders struct { streamID uint32 hf []hpack.HeaderField - endStream bool // Valid on server side. - initStream func(uint32) error // Used only on the client side. + initStream func(uint32) error onWrite func() - wq *writeQuota // write quota for the stream created. - cleanup *cleanupStream // Valid on the server side. - onOrphaned func(error) // Valid on client-side + wq *writeQuota + onOrphaned func(error) } -func (h *headerFrame) isTransportResponseFrame() bool { - return h.cleanup != nil && h.cleanup.rst // Results in a RST_STREAM +func (*clientHeaders) isThrottled() bool { return false } + +type serverHeaders struct { + streamID uint32 + hf []hpack.HeaderField + endStream bool + onWrite func() + cleanup *cleanupStream } +func (h *serverHeaders) isThrottled() bool { return false } + type cleanupStream struct { + throttledItem streamID uint32 rst bool rstCode http2.ErrCode onWrite func() } -func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM - type earlyAbortStream struct { + throttledItem streamID uint32 rst bool hf []hpack.HeaderField // Pre-built header fields } -func (*earlyAbortStream) isTransportResponseFrame() bool { return false } - type dataFrame struct { streamID uint32 endStream bool @@ -162,70 +172,60 @@ type dataFrame struct { onEachWrite func() } -func (*dataFrame) isTransportResponseFrame() bool { return false } +func (*dataFrame) isThrottled() bool { return false } type incomingWindowUpdate struct { + throttledItem streamID uint32 increment uint32 } -func (*incomingWindowUpdate) isTransportResponseFrame() bool { return false } - type outgoingWindowUpdate struct { + throttledItem streamID uint32 increment uint32 } -func (*outgoingWindowUpdate) isTransportResponseFrame() bool { - return false // window updates are throttled by thresholds -} - type incomingSettings struct { + throttledItem ss []http2.Setting } -func (*incomingSettings) isTransportResponseFrame() bool { return true } // Results in a settings ACK - type outgoingSettings struct { + throttledItem ss []http2.Setting } -func (*outgoingSettings) isTransportResponseFrame() bool { return false } - type incomingGoAway struct { + throttledItem } -func (*incomingGoAway) isTransportResponseFrame() bool { return false } - type goAway struct { + throttledItem code http2.ErrCode debugData []byte headsUp bool closeConn error // if set, loopyWriter will exit with this error } -func (*goAway) isTransportResponseFrame() bool { return false } - type ping struct { + throttledItem ack bool data [8]byte } -func (*ping) isTransportResponseFrame() bool { return true } - type outFlowControlSizeRequest struct { + throttledItem resp chan uint32 } -func (*outFlowControlSizeRequest) isTransportResponseFrame() bool { return false } - // closeConnection is an instruction to tell the loopy writer to flush the // framer and exit, which will cause the transport's connection to be closed // (by the client or server). The transport itself will close after the reader // encounters the EOF caused by the connection closure. -type closeConnection struct{} - -func (closeConnection) isTransportResponseFrame() bool { return false } +type closeConnection struct { + throttledItem +} type outStreamState int @@ -379,9 +379,9 @@ func (c *controlBuffer) executeAndPut(f func() bool, it cbItem) (bool, error) { c.consumerWaiting = false } c.list.enqueue(it) - if it.isTransportResponseFrame() { + if it.isThrottled() { c.transportResponseFrames++ - if c.transportResponseFrames == maxQueuedTransportResponseFrames { + if c.transportResponseFrames == maxQueuedControlBufferItems { // We are adding the frame that puts us over the threshold; create // a throttling channel. ch := make(chan struct{}) @@ -436,8 +436,8 @@ func (c *controlBuffer) getOnceLocked() (any, error) { return nil, nil } h := c.list.dequeue().(cbItem) - if h.isTransportResponseFrame() { - if c.transportResponseFrames == maxQueuedTransportResponseFrames { + if h.isThrottled() { + if c.transportResponseFrames == maxQueuedControlBufferItems { // We are removing the frame that put us over the // threshold; close and clear the throttling channel. ch := c.trfChan.Swap(nil) @@ -464,10 +464,8 @@ func (c *controlBuffer) finish() { // is still not aware of these yet. for head := c.list.dequeueAll(); head != nil; head = head.next { switch v := head.it.(type) { - case *headerFrame: - if v.onOrphaned != nil { // It will be nil on the server-side. - v.onOrphaned(ErrConnClosing) - } + case *clientHeaders: + v.onOrphaned(ErrConnClosing) case *dataFrame: if !v.processing { v.data.Free() @@ -680,42 +678,38 @@ func (l *loopyWriter) registerStreamHandler(h *registerStream) { l.estdStreams[h.streamID] = str } -func (l *loopyWriter) headerHandler(h *headerFrame) error { - if l.side == serverSide { - str, ok := l.estdStreams[h.streamID] - if !ok { - if l.logger.V(logLevel) { - l.logger.Infof("Unrecognized streamID %d in loopyWriter", h.streamID) - } - return nil +func (l *loopyWriter) serverHeaderHandler(hdr *serverHeaders) error { + str, ok := l.estdStreams[hdr.streamID] + if !ok { + if l.logger.V(logLevel) { + l.logger.Infof("Unrecognized streamID %d in loopyWriter", hdr.streamID) } - // Case 1.A: Server is responding back with headers. - if !h.endStream { - return l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite) - } - // else: Case 1.B: Server wants to close stream. + return nil + } - if str.state != empty { // either active or waiting on stream quota. - // add it str's list of items. - str.itl.enqueue(h) - return nil - } - if err := l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite); err != nil { - return err - } - return l.cleanupStreamHandler(h.cleanup) + // Case 1: Server is responding back with headers. + if !hdr.endStream { + return l.writeHeader(hdr.streamID, hdr.endStream, hdr.hf, hdr.onWrite) } - // Case 2: Client wants to originate stream. - str := &outStream{ - id: h.streamID, - state: empty, - itl: &itemList{}, - wq: h.wq, + + // Case 2: Server is closing the stream. + if str.state != empty { // either active or waiting on stream quota. + str.itl.enqueue(hdr) + return nil } - return l.originateStream(str, h) + if err := l.writeHeader(hdr.streamID, hdr.endStream, hdr.hf, hdr.onWrite); err != nil { + return err + } + return l.cleanupStreamHandler(hdr.cleanup) } -func (l *loopyWriter) originateStream(str *outStream, hdr *headerFrame) error { +func (l *loopyWriter) clientHeaderHandler(hdr *clientHeaders) error { + str := &outStream{ + id: hdr.streamID, + state: empty, + itl: &itemList{}, + wq: hdr.wq, + } // l.draining is set when handling GoAway. In which case, we want to avoid // creating new streams. if l.draining { @@ -726,7 +720,7 @@ func (l *loopyWriter) originateStream(str *outStream, hdr *headerFrame) error { if err := hdr.initStream(str.id); err != nil { return err } - if err := l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil { + if err := l.writeHeader(str.id, false, hdr.hf, hdr.onWrite); err != nil { return err } l.estdStreams[str.id] = str @@ -882,8 +876,10 @@ func (l *loopyWriter) handle(i any) error { return l.incomingSettingsHandler(i) case *outgoingSettings: return l.outgoingSettingsHandler(i) - case *headerFrame: - return l.headerHandler(i) + case *clientHeaders: + return l.clientHeaderHandler(i) + case *serverHeaders: + return l.serverHeaderHandler(i) case *registerStream: l.registerStreamHandler(i) case *cleanupStream: @@ -1022,7 +1018,7 @@ func (l *loopyWriter) processData() (bool, error) { func (l *loopyWriter) updateStreamAfterWrite(str *outStream) error { if str.itl.isEmpty() { str.state = empty - } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers. + } else if trailer, ok := str.itl.peek().(*serverHeaders); ok { // the next item is trailers. if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil { return err } diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go index 133f5d7065..c19b45080e 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go @@ -498,7 +498,6 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr, handler s ct: t, done: make(chan struct{}), headerChan: make(chan struct{}), - doneFunc: callHdr.DoneFunc, statsHandler: handler, } s.Stream.buf.init() @@ -806,9 +805,8 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr, handler s close(s.headerChan) } } - hdr := &headerFrame{ - hf: headerFields, - endStream: false, + hdr := &clientHeaders{ + hf: headerFields, initStream: func(uint32) error { t.mu.Lock() // TODO: handle transport closure in loopy instead and remove this @@ -999,9 +997,6 @@ func (t *http2Client) closeStream(s *ClientStream, err error, rst bool, rstCode t.controlBuf.executeAndPut(addBackStreamQuota, cleanup) // This will unblock write. close(s.done) - if s.doneFunc != nil { - s.doneFunc() - } } // Close kicks off the shutdown process of the transport. This should be called @@ -1251,7 +1246,10 @@ func (t *http2Client) handleData(f *parsedDataFrame) { dataLen := f.data.Len() if f.Header().Flags.Has(http2.FlagDataPadded) { if w := s.fc.onRead(size - uint32(dataLen)); w > 0 { - t.controlBuf.put(&outgoingWindowUpdate{s.id, w}) + t.controlBuf.put(&outgoingWindowUpdate{ + streamID: s.id, + increment: w, + }) } } if dataLen > 0 { @@ -1879,7 +1877,7 @@ func (t *http2Client) getOutFlowWindow() int64 { resp := make(chan uint32, 1) timer := time.NewTimer(time.Second) defer timer.Stop() - t.controlBuf.put(&outFlowControlSizeRequest{resp}) + t.controlBuf.put(&outFlowControlSizeRequest{resp: resp}) select { case sz := <-resp: return int64(sz) diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go index 1acd44be4b..be8ae9f9c5 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go @@ -810,7 +810,10 @@ func (t *http2Server) handleData(f *parsedDataFrame) { dataLen := f.data.Len() if f.Header().Flags.Has(http2.FlagDataPadded) { if w := s.fc.onRead(size - uint32(dataLen)); w > 0 { - t.controlBuf.put(&outgoingWindowUpdate{s.id, w}) + t.controlBuf.put(&outgoingWindowUpdate{ + streamID: s.id, + increment: w, + }) } } if dataLen > 0 { @@ -1047,7 +1050,7 @@ func (t *http2Server) writeHeaderLocked(s *ServerStream) error { headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress}) } headerFields = appendHeaderFieldsFromMD(headerFields, s.header) - hf := &headerFrame{ + hf := &serverHeaders{ streamID: s.id, hf: headerFields, endStream: false, @@ -1115,7 +1118,7 @@ func (t *http2Server) writeStatus(s *ServerStream, st *status.Status) error { // Attach the trailer metadata. headerFields = appendHeaderFieldsFromMD(headerFields, s.trailer) - trailingHeader := &headerFrame{ + trailingHeader := &serverHeaders{ streamID: s.id, hf: headerFields, endStream: true, @@ -1325,7 +1328,7 @@ func (t *http2Server) deleteStream(s *ServerStream, eosReceived bool) { } // finishStream closes the stream and puts the trailing headerFrame into controlbuf. -func (t *http2Server) finishStream(s *ServerStream, rst bool, rstCode http2.ErrCode, hdr *headerFrame, eosReceived bool) { +func (t *http2Server) finishStream(s *ServerStream, rst bool, rstCode http2.ErrCode, hdr *serverHeaders, eosReceived bool) { // In case stream sending and receiving are invoked in separate // goroutines (e.g., bi-directional streaming), cancel needs to be // called to interrupt the potential blocking on other goroutines. @@ -1464,7 +1467,7 @@ func (t *http2Server) getOutFlowWindow() int64 { resp := make(chan uint32, 1) timer := time.NewTimer(time.Second) defer timer.Stop() - t.controlBuf.put(&outFlowControlSizeRequest{resp}) + t.controlBuf.put(&outFlowControlSizeRequest{resp: resp}) select { case sz := <-resp: return int64(sz) diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go index 6dfae39849..d2e49538f0 100644 --- a/vendor/google.golang.org/grpc/internal/transport/transport.go +++ b/vendor/google.golang.org/grpc/internal/transport/transport.go @@ -594,8 +594,6 @@ type CallHdr struct { PreviousAttempts int // value of grpc-previous-rpc-attempts header to set - DoneFunc func() // called when the stream is finished - // Authority is used to explicitly override the `:authority` header. // // This value comes from one of two sources: diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go index 4aac644a83..51aff85dfb 100644 --- a/vendor/google.golang.org/grpc/stream.go +++ b/vendor/google.golang.org/grpc/stream.go @@ -201,6 +201,15 @@ func endOfClientStream(cc *ClientConn, err error, opts ...CallOption) { } } +// clientInterceptor is structurally identical to the ClientInterceptor defined +// in internal/xds/httpfilter/httpfilter.go. It is defined locally here so that +// we can type-assert the generic Interceptor field in iresolver.RPCConfig +// without introducing a dependency on xDS packages. +type clientInterceptor interface { + NewStream(ctx context.Context, ri iresolver.RPCInfo, newStream func(ctx context.Context, opts ...CallOption) (ClientStream, error), opts ...CallOption) (ClientStream, error) + Close() +} + func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { if channelz.IsOn() { cc.incrCallsStarted() @@ -244,8 +253,11 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth mc := &emptyMethodConfig var onCommit func() - newStream := func(ctx context.Context, done func()) (iresolver.ClientStream, error) { - return newClientStreamWithParams(ctx, desc, cc, method, mc, onCommit, done, nameResolutionDelayed, opts...) + newStream := func(ctx context.Context, filterOpts ...CallOption) (ClientStream, error) { + if filterOpts != nil { + opts = combine(opts, filterOpts) + } + return newClientStreamWithParams(ctx, desc, cc, method, mc, onCommit, nameResolutionDelayed, opts...) } rpcInfo := iresolver.RPCInfo{Context: ctx, Method: method} @@ -270,20 +282,24 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth if rpcConfig.Interceptor != nil { rpcInfo.Context = nil ns := newStream - newStream = func(ctx context.Context, done func()) (iresolver.ClientStream, error) { - cs, err := rpcConfig.Interceptor.NewStream(ctx, rpcInfo, done, ns) - if err != nil { - return nil, toRPCErr(err) + if interceptor, ok := rpcConfig.Interceptor.(clientInterceptor); ok { + newStream = func(ctx context.Context, filterOpts ...CallOption) (ClientStream, error) { + cs, err := interceptor.NewStream(ctx, rpcInfo, ns, filterOpts...) + if err != nil { + return nil, toRPCErr(err) + } + return cs, nil } - return cs, nil + } else { + return nil, status.Errorf(codes.Internal, "invalid client interceptor type %T", rpcConfig.Interceptor) } } } - return newStream(ctx, func() {}) + return newStream(ctx) } -func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, mc *serviceconfig.MethodConfig, onCommit, doneFunc func(), nameResolutionDelayed bool, opts ...CallOption) (_ iresolver.ClientStream, err error) { +func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, mc *serviceconfig.MethodConfig, onCommit func(), nameResolutionDelayed bool, opts ...CallOption) (_ ClientStream, err error) { callInfo := defaultCallInfo() if mc.WaitForReady != nil { callInfo.failFast = !*mc.WaitForReady @@ -321,7 +337,6 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client Host: cc.authority, Method: method, ContentSubtype: callInfo.contentSubtype, - DoneFunc: doneFunc, Authority: callInfo.authority, } if allowed := callInfo.acceptedResponseCompressors; len(allowed) > 0 { diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index cf114ef4bc..4083c03908 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.82.0" +const Version = "1.83.0" diff --git a/vendor/modules.txt b/vendor/modules.txt index c7fe23c00c..f03b6ecb59 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2071,9 +2071,6 @@ github.com/testcontainers/testcontainers-go/wait # github.com/testcontainers/testcontainers-go/modules/opensearch v0.43.0 ## explicit; go 1.25.0 github.com/testcontainers/testcontainers-go/modules/opensearch -# github.com/theckman/yacspin v0.13.12 -## explicit; go 1.17 -github.com/theckman/yacspin # github.com/thejerf/suture/v4 v4.0.6 ## explicit; go 1.9 github.com/thejerf/suture/v4 @@ -2574,7 +2571,7 @@ google.golang.org/genproto/googleapis/api/httpbody ## explicit; go 1.25.0 google.golang.org/genproto/googleapis/rpc/errdetails google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.82.0 +# google.golang.org/grpc v1.83.0 ## explicit; go 1.25.0 google.golang.org/grpc google.golang.org/grpc/attributes