Compare commits
137 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
c54eac28fd | |
|
|
6caf0e77fa | |
|
|
1ad1dc15dd | |
|
|
f575e91b2c | |
|
|
ed672b2bc9 | |
|
|
eab6c910a6 | |
|
|
60e53f304f | |
|
|
f093930c85 | |
|
|
7ad93a42d9 | |
|
|
7155fb6211 | |
|
|
f28d506cea | |
|
|
58ccc6321e | |
|
|
b519ffc959 | |
|
|
3a8fa31879 | |
|
|
614b1687cf | |
|
|
30f87c1323 | |
|
|
78655b4786 | |
|
|
d00c28104b | |
|
|
9e3e083f29 | |
|
|
c32936d71e | |
|
|
f3c8ec2564 | |
|
|
7e1a6c9068 | |
|
|
b9a11e9fea | |
|
|
bc5cf811a0 | |
|
|
fb49f049e6 | |
|
|
cdb43b08fa | |
|
|
56181ba330 | |
|
|
46c38b351a | |
|
|
a05d48d6dd | |
|
|
fc63514da1 | |
|
|
e14d9f769a | |
|
|
239dde4a62 | |
|
|
80e833a557 | |
|
|
6fccd7757e | |
|
|
400fa5f2d3 | |
|
|
0e13e85e65 | |
|
|
07361b21ea | |
|
|
8e76884d21 | |
|
|
805ce40c63 | |
|
|
93ea011b36 | |
|
|
5592211a41 | |
|
|
184c8f70b5 | |
|
|
149a93e0ec | |
|
|
252b57fd45 | |
|
|
24b80dfed8 | |
|
|
334e3f56de | |
|
|
f4157743ed | |
|
|
79fb35f680 | |
|
|
7ccaf0a21f | |
|
|
6093b09afa | |
|
|
70c215f7e2 | |
|
|
28c0ee28f0 | |
|
|
bc2944de97 | |
|
|
7a845ca5e9 | |
|
|
c17f0782f7 | |
|
|
42f63028d4 | |
|
|
743e60a4c9 | |
|
|
b7a5d3bba8 | |
|
|
2a29c1e64b | |
|
|
9a59bed1d2 | |
|
|
ae7dadff19 | |
|
|
3961a33e7f | |
|
|
d5b8e4d4ce | |
|
|
0efcfa65f2 | |
|
|
fae58803d9 | |
|
|
1fda47eb90 | |
|
|
031cd3d1e7 | |
|
|
a5037bdf4a | |
|
|
4775fb574b | |
|
|
b96cb4ddd0 | |
|
|
006918123d | |
|
|
66a2405833 | |
|
|
dfd889a44b | |
|
|
a3a5bcd8ab | |
|
|
61a9c00d87 | |
|
|
85f1cbf7ad | |
|
|
dd2f60135c | |
|
|
81c624c41f | |
|
|
3826617999 | |
|
|
8d60b618ac | |
|
|
47b842a805 | |
|
|
898bdad041 | |
|
|
25c896aa59 | |
|
|
0d0992e6a2 | |
|
|
8093376ece | |
|
|
fec466efa6 | |
|
|
7f919e6459 | |
|
|
0df5c93e8d | |
|
|
353e0953cb | |
|
|
c9ac3da95f | |
|
|
ea24a77215 | |
|
|
c3fbeaff64 | |
|
|
7860209a53 | |
|
|
b953ea196a | |
|
|
683a7fb09c | |
|
|
8bb6eeb0d0 | |
|
|
805e231182 | |
|
|
aa5998a119 | |
|
|
b34b13bab3 | |
|
|
b890db745f | |
|
|
57a2cd1a09 | |
|
|
ae7473c7a7 | |
|
|
b3f576068c | |
|
|
8ee6c9423b | |
|
|
4b65b3ee55 | |
|
|
9ac7e3a34d | |
|
|
76bbedeed0 | |
|
|
b9d2d8cfa8 | |
|
|
30b8cd1531 | |
|
|
a8f79c8751 | |
|
|
bf9b13d6c5 | |
|
|
c3bde04cc1 | |
|
|
2e9ba5024e | |
|
|
127194b205 | |
|
|
cd242fe1ed | |
|
|
59a32e5eb0 | |
|
|
7e1cd16164 | |
|
|
de25c89822 | |
|
|
f1d396c31e | |
|
|
1986364acd | |
|
|
bdf97bc934 | |
|
|
2f55ac63a4 | |
|
|
8d7770a962 | |
|
|
1f34448998 | |
|
|
06a970022e | |
|
|
db90ec1160 | |
|
|
9da71fbe53 | |
|
|
9846afccbc | |
|
|
ba5f667e13 | |
|
|
54ffdcacda | |
|
|
ceef817807 | |
|
|
e544b9e66f | |
|
|
41a6ac0479 | |
|
|
f37ec641c5 | |
|
|
8e51c5e2d3 | |
|
|
8376c2f7bb | |
|
|
0162fa9726 |
|
|
@ -0,0 +1,40 @@
|
|||
shared_configs:
|
||||
simple_job_steps: &simple_job_steps
|
||||
- checkout
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
make test
|
||||
|
||||
# Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference
|
||||
version: 2.1
|
||||
jobs:
|
||||
build-1-23:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: cimg/go:1.23
|
||||
steps: *simple_job_steps
|
||||
|
||||
build-1-24:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: cimg/go:1.24
|
||||
steps: *simple_job_steps
|
||||
|
||||
build-1-25:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: cimg/go:1.25
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Run tests and linters
|
||||
command: |
|
||||
make ci
|
||||
|
||||
workflows:
|
||||
pr-build-test:
|
||||
jobs:
|
||||
- build-1-23
|
||||
- build-1-24
|
||||
- build-1-25
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
# Check for updates once a week
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# This workflow was added by CodeSee. Learn more at https://codesee.io/
|
||||
# This is v2.0 of this workflow file
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
name: CodeSee
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
codesee:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
name: Analyze the repo with CodeSee
|
||||
steps:
|
||||
- uses: Codesee-io/codesee-action@v2
|
||||
with:
|
||||
codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }}
|
||||
|
|
@ -1,2 +1,5 @@
|
|||
dist/
|
||||
.idea/
|
||||
VERSION
|
||||
.tmp/
|
||||
*.snap
|
||||
|
|
|
|||
|
|
@ -8,17 +8,56 @@ builds:
|
|||
goarch:
|
||||
- amd64
|
||||
- 386
|
||||
- arm
|
||||
- arm64
|
||||
- s390x
|
||||
- ppc64le
|
||||
goarm:
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: s390x
|
||||
- goos: windows
|
||||
goarch: s390x
|
||||
- goos: darwin
|
||||
goarch: ppc64le
|
||||
- goos: windows
|
||||
goarch: ppc64le
|
||||
ldflags:
|
||||
- -s -w -X main.version=v{{.Version}}
|
||||
|
||||
archives:
|
||||
- format: tar.gz
|
||||
name_template: >-
|
||||
{{ .Binary }}_{{ .Version }}_
|
||||
{{- if eq .Os "darwin" }}osx{{ else }}{{ .Os }}{{ end }}_
|
||||
{{- if eq .Arch "amd64" }}x86_64
|
||||
{{- else if eq .Arch "386" }}x86_32
|
||||
{{- else }}{{ .Arch }}{{ end }}
|
||||
{{- with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
replacements:
|
||||
amd64: x86_64
|
||||
386: x86_32
|
||||
darwin: osx
|
||||
files:
|
||||
- LICENSE
|
||||
|
||||
nfpms:
|
||||
- vendor: Fullstory
|
||||
homepage: https://github.com/fullstorydev/grpcurl/
|
||||
maintainer: Engineering at Fullstory <fixme@fixme>
|
||||
description: 'Like cURL, but for gRPC: Command-line tool for interacting with gRPC servers'
|
||||
license: MIT
|
||||
id: nfpms
|
||||
formats:
|
||||
- deb
|
||||
- rpm
|
||||
|
|
|
|||
24
.travis.yml
24
.travis.yml
|
|
@ -1,24 +0,0 @@
|
|||
language: go
|
||||
sudo: false
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.11.x
|
||||
env: GO111MODULE=off
|
||||
- go: 1.11.x
|
||||
env: GO111MODULE=on
|
||||
- go: 1.12.x
|
||||
env: GO111MODULE=off
|
||||
- go: 1.12.x
|
||||
env: GO111MODULE=on
|
||||
- go: 1.13.x
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- VET=1
|
||||
- go: 1.14.x
|
||||
env: GO111MODULE=on
|
||||
- go: tip
|
||||
env: GO111MODULE=on
|
||||
|
||||
script:
|
||||
- if [[ "$VET" = 1 ]]; then make ci; else make deps test; fi
|
||||
15
Dockerfile
15
Dockerfile
|
|
@ -1,5 +1,5 @@
|
|||
FROM golang:1.13-alpine as builder
|
||||
MAINTAINER FullStory Engineering
|
||||
FROM golang:1.25-alpine AS builder
|
||||
LABEL maintainer="Fullstory Engineering"
|
||||
|
||||
# create non-privileged group and user
|
||||
RUN addgroup -S grpcurl && adduser -S grpcurl -G grpcurl
|
||||
|
|
@ -11,13 +11,20 @@ COPY cmd /tmp/fullstorydev/grpcurl/cmd
|
|||
# and build a completely static binary (so we can use
|
||||
# scratch as basis for the final image)
|
||||
ENV CGO_ENABLED=0
|
||||
ENV GOOS=linux
|
||||
ENV GOARCH=amd64
|
||||
ENV GO111MODULE=on
|
||||
RUN go build -o /grpcurl \
|
||||
-ldflags "-w -extldflags \"-static\" -X \"main.version=$(cat VERSION)\"" \
|
||||
./cmd/grpcurl
|
||||
|
||||
FROM alpine:3 AS alpine
|
||||
WORKDIR /
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
COPY --from=builder /etc/passwd /etc/passwd
|
||||
COPY --from=builder /grpcurl /bin/grpcurl
|
||||
USER grpcurl
|
||||
|
||||
ENTRYPOINT ["/bin/grpcurl"]
|
||||
|
||||
# New FROM so we have a nice'n'tiny image
|
||||
FROM scratch
|
||||
WORKDIR /
|
||||
|
|
|
|||
4
LICENSE
4
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 FullStory, Inc
|
||||
Copyright (c) 2017 Fullstory, Inc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
|
|
|
|||
55
Makefile
55
Makefile
|
|
@ -1,20 +1,29 @@
|
|||
dev_build_version=$(shell git describe --tags --always --dirty)
|
||||
|
||||
export PATH := $(shell pwd)/.tmp/protoc/bin:$(PATH)
|
||||
export PROTOC_VERSION := 22.0
|
||||
# Disable CGO for improved compatibility across distros
|
||||
export CGO_ENABLED=0
|
||||
export GOFLAGS=-trimpath
|
||||
export GOWORK=off
|
||||
|
||||
# TODO: run golint and errcheck, but only to catch *new* violations and
|
||||
# decide whether to change code or not (e.g. we need to be able to whitelist
|
||||
# violations already in the code). They can be useful to catch errors, but
|
||||
# they are just too noisy to be a requirement for a CI -- we don't even *want*
|
||||
# to fix some of the things they consider to be violations.
|
||||
.PHONY: ci
|
||||
ci: deps checkgofmt vet staticcheck ineffassign predeclared test
|
||||
ci: deps checkgofmt checkgenerate vet staticcheck ineffassign predeclared test
|
||||
|
||||
.PHONY: deps
|
||||
deps:
|
||||
go get -d -v -t ./...
|
||||
go mod tidy
|
||||
|
||||
.PHONY: updatedeps
|
||||
updatedeps:
|
||||
go get -d -v -t -u -f ./...
|
||||
go mod tidy
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
|
|
@ -22,8 +31,8 @@ install:
|
|||
|
||||
.PHONY: release
|
||||
release:
|
||||
@go get github.com/goreleaser/goreleaser
|
||||
goreleaser --rm-dist
|
||||
@go install github.com/goreleaser/goreleaser@v1.21.0
|
||||
goreleaser release --clean
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
|
|
@ -31,6 +40,22 @@ docker:
|
|||
docker build -t fullstorydev/grpcurl:$(dev_build_version) .
|
||||
@rm VERSION
|
||||
|
||||
.PHONY: generate
|
||||
generate: .tmp/protoc/bin/protoc
|
||||
@go install google.golang.org/protobuf/cmd/protoc-gen-go@a709e31e5d12
|
||||
@go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0
|
||||
@go install github.com/jhump/protoreflect/desc/sourceinfo/cmd/protoc-gen-gosrcinfo@v1.14.1
|
||||
go generate ./...
|
||||
go mod tidy
|
||||
|
||||
.PHONY: checkgenerate
|
||||
checkgenerate: generate
|
||||
git status --porcelain -- '**/*.go'
|
||||
@if [ -n "$$(git status --porcelain -- '**/*.go')" ]; then \
|
||||
git diff -- '**/*.go'; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: checkgofmt
|
||||
checkgofmt:
|
||||
gofmt -s -l .
|
||||
|
|
@ -42,35 +67,37 @@ checkgofmt:
|
|||
vet:
|
||||
go vet ./...
|
||||
|
||||
# This all works fine with Go modules, but without modules,
|
||||
# CI is just getting latest master for dependencies like grpc.
|
||||
.PHONY: staticcheck
|
||||
staticcheck:
|
||||
@go get honnef.co/go/tools/cmd/staticcheck
|
||||
staticcheck ./...
|
||||
@go install honnef.co/go/tools/cmd/staticcheck@2025.1.1
|
||||
staticcheck -checks "inherit,-SA1019" ./...
|
||||
|
||||
.PHONY: ineffassign
|
||||
ineffassign:
|
||||
@go get github.com/gordonklaus/ineffassign
|
||||
@go install github.com/gordonklaus/ineffassign@7953dde2c7bf
|
||||
ineffassign .
|
||||
|
||||
.PHONY: predeclared
|
||||
predeclared:
|
||||
@go get github.com/nishanths/predeclared
|
||||
predeclared .
|
||||
@go install github.com/nishanths/predeclared@51e8c974458a0f93dc03fe356f91ae1a6d791e6f
|
||||
predeclared ./...
|
||||
|
||||
# Intentionally omitted from CI, but target here for ad-hoc reports.
|
||||
.PHONY: golint
|
||||
golint:
|
||||
@go get golang.org/x/lint/golint
|
||||
@go install golang.org/x/lint/golint@v0.0.0-20210508222113-6edffad5e616
|
||||
golint -min_confidence 0.9 -set_exit_status ./...
|
||||
|
||||
# Intentionally omitted from CI, but target here for ad-hoc reports.
|
||||
.PHONY: errcheck
|
||||
errcheck:
|
||||
@go get github.com/kisielk/errcheck
|
||||
@go install github.com/kisielk/errcheck@v1.2.0
|
||||
errcheck ./...
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race ./...
|
||||
test: deps
|
||||
CGO_ENABLED=1 go test -race ./...
|
||||
|
||||
.tmp/protoc/bin/protoc: ./Makefile ./download_protoc.sh
|
||||
./download_protoc.sh
|
||||
|
||||
|
|
|
|||
85
README.md
85
README.md
|
|
@ -1,6 +1,7 @@
|
|||
# gRPCurl
|
||||
[](https://travis-ci.com/github/fullstorydev/grpcurl/branches)
|
||||
[](https://circleci.com/gh/fullstorydev/grpcurl/tree/master)
|
||||
[](https://goreportcard.com/report/github.com/fullstorydev/grpcurl)
|
||||
[](https://snapcraft.io/grpcurl)
|
||||
|
||||
`grpcurl` is a command-line tool that lets you interact with gRPC servers. It's
|
||||
basically `curl` for gRPC servers.
|
||||
|
|
@ -14,7 +15,7 @@ This program accepts messages using JSON encoding, which is much more friendly f
|
|||
humans and scripts.
|
||||
|
||||
With this tool you can also browse the schema for gRPC services, either by querying
|
||||
a server that supports [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto),
|
||||
a server that supports [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto),
|
||||
by reading proto source files, or by loading in compiled "protoset" files (files that contain
|
||||
encoded file [descriptor protos](https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto)).
|
||||
In fact, the way the tool transforms JSON request data into a binary encoded protobuf
|
||||
|
|
@ -35,9 +36,9 @@ See also the [`grpcurl` talk at GopherCon 2018](https://www.youtube.com/watch?v=
|
|||
operate bi-directional streaming methods interactively by running `grpcurl` from an
|
||||
interactive terminal and using stdin as the request body!
|
||||
|
||||
`grpcurl` supports both plain-text and TLS servers and has numerous options for TLS
|
||||
configuration. It also supports mutual TLS, where the client is required to present a
|
||||
client certificate.
|
||||
`grpcurl` supports both secure/TLS servers _and_ plain-text servers (i.e. no TLS) and has
|
||||
numerous options for TLS configuration. It also supports mutual TLS, where the client is
|
||||
required to present a client certificate.
|
||||
|
||||
As mentioned above, `grpcurl` works seamlessly if the server supports the reflection
|
||||
service. If not, you can supply the `.proto` source files or you can supply protoset
|
||||
|
|
@ -49,32 +50,63 @@ files (containing compiled descriptors, produced by `protoc`) to `grpcurl`.
|
|||
|
||||
Download the binary from the [releases](https://github.com/fullstorydev/grpcurl/releases) page.
|
||||
|
||||
### Homebrew (macOS)
|
||||
|
||||
On macOS, `grpcurl` is available via Homebrew:
|
||||
```shell
|
||||
brew install grpcurl
|
||||
```
|
||||
|
||||
### From Source
|
||||
You can use the `go` tool to install `grpcurl`:
|
||||
### Docker
|
||||
|
||||
For platforms that support Docker, you can download an image that lets you run `grpcurl`:
|
||||
```shell
|
||||
go get github.com/fullstorydev/grpcurl
|
||||
go install github.com/fullstorydev/grpcurl/cmd/grpcurl
|
||||
# Download image
|
||||
docker pull fullstorydev/grpcurl:latest
|
||||
# Run the tool
|
||||
docker run fullstorydev/grpcurl api.grpc.me:443 list
|
||||
```
|
||||
Note that there are some pitfalls when using docker:
|
||||
- If you need to interact with a server listening on the host's loopback network, you must specify the host as `host.docker.internal` instead of `localhost` (for Mac or Windows) _OR_ have the container use the host network with `-network="host"` (Linux only).
|
||||
- If you need to provide proto source files or descriptor sets, you must mount the folder containing the files as a volume (`-v $(pwd):/protos`) and adjust the import paths to container paths accordingly.
|
||||
- If you want to provide the request message via stdin, using the `-d @` option, you need to use the `-i` flag on the docker command.
|
||||
|
||||
### Other Packages
|
||||
|
||||
There are numerous other ways to install `grpcurl`, thanks to support from third parties that
|
||||
have created recipes/packages for it. These include other ways to install `grpcurl` on a variety
|
||||
of environments, including Windows and myriad Linux distributions.
|
||||
|
||||
You can see more details and the full list of other packages for `grpcurl` at _repology.org_:
|
||||
https://repology.org/project/grpcurl/information
|
||||
|
||||
### Snap
|
||||
|
||||
You can install `grpcurl` using the snap package:
|
||||
|
||||
`snap install grpcurl`
|
||||
|
||||
### From Source
|
||||
If you already have the [Go SDK](https://golang.org/doc/install) installed, you can use the `go`
|
||||
tool to install `grpcurl`:
|
||||
```shell
|
||||
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
|
||||
```
|
||||
|
||||
This installs the command into the `bin` sub-folder of wherever your `$GOPATH`
|
||||
environment variable points. If this directory is already in your `$PATH`, then
|
||||
you should be good to go.
|
||||
environment variable points. (If you have no `GOPATH` environment variable set,
|
||||
the default install location is `$HOME/go/bin`). If this directory is already in
|
||||
your `$PATH`, then you should be good to go.
|
||||
|
||||
If you have already pulled down this repo to a location that is not in your
|
||||
`$GOPATH` and want to build from the sources, you can `cd` into the repo and then
|
||||
run `make install`.
|
||||
|
||||
If you encounter compile errors, you could have out-dated versions of `grpcurl`'s
|
||||
dependencies. You can update the dependencies by running `make updatedeps`. You can
|
||||
also use [`vgo`](https://github.com/golang/vgo) to install, which will use the right
|
||||
versions of dependencies. Or, if you are using Go 1.11, you can add `GO111MODULE=on`
|
||||
as a prefix to the commands above, which will also build using the right versions of
|
||||
dependencies (vs. whatever you may already in your `GOPATH`).
|
||||
If you encounter compile errors and are using a version of the Go SDK older than 1.13,
|
||||
you could have out-dated versions of `grpcurl`'s dependencies. You can update the
|
||||
dependencies by running `make updatedeps`. Or, if you are using Go 1.11 or 1.12, you
|
||||
can add `GO111MODULE=on` as a prefix to the commands above, which will also build using
|
||||
the right versions of dependencies (vs. whatever you may already have in your `GOPATH`).
|
||||
|
||||
## Usage
|
||||
The usage doc for the tool explains the numerous options:
|
||||
|
|
@ -91,6 +123,9 @@ that requires no client certs and supports server reflection is the simplest thi
|
|||
do with `grpcurl`. This minimal invocation sends an empty request body:
|
||||
```shell
|
||||
grpcurl grpc.server.com:443 my.custom.server.Service/Method
|
||||
|
||||
# no TLS
|
||||
grpcurl -plaintext grpc.server.com:80 my.custom.server.Service/Method
|
||||
```
|
||||
|
||||
To send a non-empty request, use the `-d` argument. Note that all arguments must come
|
||||
|
|
@ -117,6 +152,13 @@ grpcurl -d @ grpc.server.com:443 my.custom.server.Service/Method <<EOM
|
|||
}
|
||||
EOM
|
||||
```
|
||||
### Adding Headers/Metadata to Request
|
||||
Adding of headers / metadata to a rpc request is possible via the `-H name:value` command line option. Multiple headers can be added in a similar fashion.
|
||||
Example :
|
||||
```shell
|
||||
grpcurl -H header1:value1 -H header2:value2 -d '{"id": 1234, "tags": ["foo","bar"]}' grpc.server.com:443 my.custom.server.Service/Method
|
||||
```
|
||||
For more usage guide, check out the help docs via `grpcurl -help`
|
||||
|
||||
### Listing Services
|
||||
To list all services exposed by a server, use the "list" verb. When using `.proto` source
|
||||
|
|
@ -131,6 +173,13 @@ grpcurl -protoset my-protos.bin list
|
|||
|
||||
# Using proto sources
|
||||
grpcurl -import-path ../protos -proto my-stuff.proto list
|
||||
|
||||
# Export proto files (use -proto-out-dir to specify the output directory)
|
||||
grpcurl -plaintext -proto-out-dir "out_protos" "localhost:8787" describe my.custom.server.Service
|
||||
|
||||
# Export protoset file (use -protoset-out to specify the output file)
|
||||
grpcurl -plaintext -protoset-out "out.protoset" "localhost:8787" describe my.custom.server.Service
|
||||
|
||||
```
|
||||
|
||||
The "list" verb also lets you see all methods in a particular service:
|
||||
|
|
@ -164,7 +213,7 @@ are needed to use them.
|
|||
|
||||
### Server Reflection
|
||||
|
||||
Without any additional command-line flags, `grpcurl` will try to use [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto).
|
||||
Without any additional command-line flags, `grpcurl` will try to use [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto).
|
||||
|
||||
Examples for how to set up server reflection can be found [here](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md#known-implementations).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
// +build go1.10
|
||||
|
||||
package main
|
||||
|
||||
func indent() string {
|
||||
// In Go 1.10 and up, the flag package automatically
|
||||
// adds the right indentation.
|
||||
return ""
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
// +build !go1.10
|
||||
|
||||
package main
|
||||
|
||||
func indent() string {
|
||||
// In Go 1.9 and older, we need to add indentation
|
||||
// after newlines in the flag doc strings.
|
||||
return " \t"
|
||||
}
|
||||
|
|
@ -4,38 +4,44 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fullstorydev/grpcurl"
|
||||
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 required to use APIs in other grpcurl package
|
||||
"github.com/jhump/protoreflect/grpcreflect"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/alts"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
|
||||
// Register gzip compressor so compressed responses will work:
|
||||
// Register gzip compressor so compressed responses will work
|
||||
_ "google.golang.org/grpc/encoding/gzip"
|
||||
// Register xds so xds and xds-experimental resolver schemes work
|
||||
_ "google.golang.org/grpc/xds"
|
||||
|
||||
"github.com/fullstorydev/grpcurl"
|
||||
)
|
||||
|
||||
// To avoid confusion between program error codes and the gRPC resonse
|
||||
// To avoid confusion between program error codes and the gRPC response
|
||||
// status codes 'Cancelled' and 'Unknown', 1 and 2 respectively,
|
||||
// the response status codes emitted use an offest of 64
|
||||
// the response status codes emitted use an offset of 64
|
||||
const statusCodeOffset = 64
|
||||
|
||||
var version = "dev build <no version set>"
|
||||
const noVersion = "dev build <no version set>"
|
||||
|
||||
var version = noVersion
|
||||
|
||||
var (
|
||||
exit = os.Exit
|
||||
|
|
@ -48,11 +54,14 @@ var (
|
|||
Print usage instructions and exit.`))
|
||||
printVersion = flags.Bool("version", false, prettify(`
|
||||
Print version.`))
|
||||
|
||||
plaintext = flags.Bool("plaintext", false, prettify(`
|
||||
Use plain-text HTTP/2 when connecting to server (no TLS).`))
|
||||
insecure = flags.Bool("insecure", false, prettify(`
|
||||
Skip server certificate and domain verification. (NOT SECURE!) Not
|
||||
valid with -plaintext option.`))
|
||||
|
||||
// TLS Options
|
||||
cacert = flags.String("cacert", "", prettify(`
|
||||
File containing trusted root certificates for verifying the server.
|
||||
Ignored if -insecure is specified.`))
|
||||
|
|
@ -62,6 +71,13 @@ var (
|
|||
key = flags.String("key", "", prettify(`
|
||||
File containing client private key, to present to the server. Not valid
|
||||
with -plaintext option. Must also provide -cert option.`))
|
||||
|
||||
// ALTS Options
|
||||
usealts = flags.Bool("alts", false, prettify(`
|
||||
Use Application Layer Transport Security (ALTS) when connecting to server.`))
|
||||
altsHandshakerServiceAddress = flags.String("alts-handshaker-service", "", prettify(`If set, this server will be used to do the ATLS handshaking.`))
|
||||
altsTargetServiceAccounts multiString
|
||||
|
||||
protoset multiString
|
||||
protoFiles multiString
|
||||
importPaths multiString
|
||||
|
|
@ -82,7 +98,12 @@ var (
|
|||
value of the ":authority" pseudo-header in the HTTP/2 protocol. When TLS
|
||||
is used, this will also be used as the server name when verifying the
|
||||
server's certificate. It defaults to the address that is provided in the
|
||||
positional arguments.`))
|
||||
positional arguments, or 'localhost' in the case of a unix domain
|
||||
socket.`))
|
||||
userAgent = flags.String("user-agent", "", prettify(`
|
||||
If set, the specified value will be added to the User-Agent header set
|
||||
by the grpc-go library.
|
||||
`))
|
||||
data = flags.String("d", "", prettify(`
|
||||
Data for request contents. If the value is '@' then the request contents
|
||||
are read from stdin. For calls that accept a stream of requests, the
|
||||
|
|
@ -98,6 +119,10 @@ var (
|
|||
ASCII character: 0x1E. The stream should not end in a record separator.
|
||||
If it does, it will be interpreted as a final, blank message after the
|
||||
separator.`))
|
||||
allowUnknownFields = flags.Bool("allow-unknown-fields", false, prettify(`
|
||||
When true, the request contents, if 'json' format is used, allows
|
||||
unknown fields to be present. They will be ignored when parsing
|
||||
the request.`))
|
||||
connectTimeout = flags.Float64("connect-timeout", 0, prettify(`
|
||||
The maximum time, in seconds, to wait for connection to be established.
|
||||
Defaults to 10 seconds.`))
|
||||
|
|
@ -110,9 +135,11 @@ var (
|
|||
is received for this same period then the connection is closed and the
|
||||
operation fails.`))
|
||||
maxTime = flags.Float64("max-time", 0, prettify(`
|
||||
The maximum total time the operation can take, in seconds. This is
|
||||
useful for preventing batch jobs that use grpcurl from hanging due to
|
||||
slow or bad network links or due to incorrect stream method usage.`))
|
||||
The maximum total time the operation can take, in seconds. This sets a
|
||||
timeout on the gRPC context, allowing both client and server to give up
|
||||
after the deadline has past. This is useful for preventing batch jobs
|
||||
that use grpcurl from hanging due to slow or bad network links or due
|
||||
to incorrect stream method usage.`))
|
||||
maxMsgSz = flags.Int("max-msg-sz", 0, prettify(`
|
||||
The maximum encoded size of a response message, in bytes, that grpcurl
|
||||
will accept. If not specified, defaults to 4,194,304 (4 megabytes).`))
|
||||
|
|
@ -125,10 +152,20 @@ var (
|
|||
file if this option is given. When invoking an RPC and this option is
|
||||
given, the method being invoked and its transitive dependencies will be
|
||||
included in the output file.`))
|
||||
protoOut = flags.String("proto-out-dir", "", prettify(`
|
||||
The name of a directory where the generated .proto files will be written.
|
||||
With the list and describe verbs, the listed or described elements and
|
||||
their transitive dependencies will be written as .proto files in the
|
||||
specified directory if this option is given. When invoking an RPC and
|
||||
this option is given, the method being invoked and its transitive
|
||||
dependencies will be included in the generated .proto files in the
|
||||
output directory.`))
|
||||
msgTemplate = flags.Bool("msg-template", false, prettify(`
|
||||
When describing messages, show a template of input data.`))
|
||||
verbose = flags.Bool("v", false, prettify(`
|
||||
Enable verbose output.`))
|
||||
veryVerbose = flags.Bool("vv", false, prettify(`
|
||||
Enable very verbose output (includes timing data).`))
|
||||
serverName = flags.String("servername", "", prettify(`
|
||||
Override server name when validating TLS certificate. This flag is
|
||||
ignored if -plaintext or -insecure is used.
|
||||
|
|
@ -143,7 +180,7 @@ func init() {
|
|||
flags.Var(&addlHeaders, "H", prettify(`
|
||||
Additional headers in 'name: value' format. May specify more than one
|
||||
via multiple flags. These headers will also be included in reflection
|
||||
requests requests to a server.`))
|
||||
requests to a server.`))
|
||||
flags.Var(&rpcHeaders, "rpc-header", prettify(`
|
||||
Additional RPC headers in 'name: value' format. May specify more than
|
||||
one via multiple flags. These headers will *only* be used when invoking
|
||||
|
|
@ -185,6 +222,14 @@ func init() {
|
|||
-use-reflection is used in combination with a -proto or -protoset flag,
|
||||
the provided descriptor sources will be used in addition to server
|
||||
reflection to resolve messages and extensions.`))
|
||||
flags.Var(&altsTargetServiceAccounts, "alts-target-service-account", prettify(`
|
||||
The full email address of the service account that the server is
|
||||
expected to be using when ALTS is used. You can specify this option
|
||||
multiple times to indicate multiple allowed service accounts. If the
|
||||
server authenticates with a service account that is not one of the
|
||||
expected accounts, the RPC will not be issued. If no such arguments are
|
||||
provided, no check will be performed, and the RPC will be issued
|
||||
regardless of the server's service account.`))
|
||||
}
|
||||
|
||||
type multiString []string
|
||||
|
|
@ -241,6 +286,32 @@ func (cs compositeSource) AllExtensionsForType(typeName string) ([]*desc.FieldDe
|
|||
return exts, nil
|
||||
}
|
||||
|
||||
type timingData struct {
|
||||
Title string
|
||||
Start time.Time
|
||||
Value time.Duration
|
||||
Parent *timingData
|
||||
Sub []*timingData
|
||||
}
|
||||
|
||||
func (d *timingData) Child(title string) *timingData {
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
child := &timingData{Title: title, Start: time.Now()}
|
||||
d.Sub = append(d.Sub, child)
|
||||
return child
|
||||
}
|
||||
|
||||
func (d *timingData) Done() {
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
if d.Value == 0 {
|
||||
d.Value = time.Since(d.Start)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flags.Usage = usage
|
||||
flags.Parse(os.Args[1:])
|
||||
|
|
@ -253,6 +324,9 @@ func main() {
|
|||
os.Exit(0)
|
||||
}
|
||||
|
||||
// default behavior is to use tls
|
||||
usetls := !*plaintext && !*usealts
|
||||
|
||||
// Do extra validation on arguments and figure out what user asked us to do.
|
||||
if *connectTimeout < 0 {
|
||||
fail(nil, "The -connect-timeout argument must not be negative.")
|
||||
|
|
@ -266,18 +340,27 @@ func main() {
|
|||
if *maxMsgSz < 0 {
|
||||
fail(nil, "The -max-msg-sz argument must not be negative.")
|
||||
}
|
||||
if *plaintext && *insecure {
|
||||
fail(nil, "The -plaintext and -insecure arguments are mutually exclusive.")
|
||||
if *plaintext && *usealts {
|
||||
fail(nil, "The -plaintext and -alts arguments are mutually exclusive.")
|
||||
}
|
||||
if *plaintext && *cert != "" {
|
||||
fail(nil, "The -plaintext and -cert arguments are mutually exclusive.")
|
||||
if *insecure && !usetls {
|
||||
fail(nil, "The -insecure argument can only be used with TLS.")
|
||||
}
|
||||
if *plaintext && *key != "" {
|
||||
fail(nil, "The -plaintext and -key arguments are mutually exclusive.")
|
||||
if *cert != "" && !usetls {
|
||||
fail(nil, "The -cert argument can only be used with TLS.")
|
||||
}
|
||||
if *key != "" && !usetls {
|
||||
fail(nil, "The -key argument can only be used with TLS.")
|
||||
}
|
||||
if (*key == "") != (*cert == "") {
|
||||
fail(nil, "The -cert and -key arguments must be used together and both be present.")
|
||||
}
|
||||
if *altsHandshakerServiceAddress != "" && !*usealts {
|
||||
fail(nil, "The -alts-handshaker-service argument must be used with the -alts argument.")
|
||||
}
|
||||
if len(altsTargetServiceAccounts) > 0 && !*usealts {
|
||||
fail(nil, "The -alts-target-service-account argument must be used with the -alts argument.")
|
||||
}
|
||||
if *format != "json" && *format != "text" {
|
||||
fail(nil, "The -format option must be 'json' or 'text'.")
|
||||
}
|
||||
|
|
@ -310,6 +393,22 @@ func main() {
|
|||
invoke = true
|
||||
}
|
||||
|
||||
verbosityLevel := 0
|
||||
if *verbose {
|
||||
verbosityLevel = 1
|
||||
}
|
||||
|
||||
var rootTiming *timingData
|
||||
if *veryVerbose {
|
||||
verbosityLevel = 2
|
||||
|
||||
rootTiming = &timingData{Title: "Timing Data", Start: time.Now()}
|
||||
defer func() {
|
||||
rootTiming.Done()
|
||||
dumpTiming(rootTiming, 0)
|
||||
}()
|
||||
}
|
||||
|
||||
var symbol string
|
||||
if invoke {
|
||||
if len(args) == 0 {
|
||||
|
|
@ -359,20 +458,24 @@ func main() {
|
|||
|
||||
ctx := context.Background()
|
||||
if *maxTime > 0 {
|
||||
timeout := time.Duration(*maxTime * float64(time.Second))
|
||||
ctx, _ = context.WithTimeout(ctx, timeout)
|
||||
timeout := floatSecondsToDuration(*maxTime)
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
dial := func() *grpc.ClientConn {
|
||||
dialTiming := rootTiming.Child("Dial")
|
||||
defer dialTiming.Done()
|
||||
dialTime := 10 * time.Second
|
||||
if *connectTimeout > 0 {
|
||||
dialTime = time.Duration(*connectTimeout * float64(time.Second))
|
||||
dialTime = floatSecondsToDuration(*connectTimeout)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, dialTime)
|
||||
defer cancel()
|
||||
var opts []grpc.DialOption
|
||||
if *keepaliveTime > 0 {
|
||||
timeout := time.Duration(*keepaliveTime * float64(time.Second))
|
||||
timeout := floatSecondsToDuration(*keepaliveTime)
|
||||
opts = append(opts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||
Time: timeout,
|
||||
Timeout: timeout,
|
||||
|
|
@ -381,13 +484,46 @@ func main() {
|
|||
if *maxMsgSz > 0 {
|
||||
opts = append(opts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(*maxMsgSz)))
|
||||
}
|
||||
if isUnixSocket != nil && isUnixSocket() && !strings.HasPrefix(target, "unix://") {
|
||||
// prepend unix:// to the address if it's not already there
|
||||
// this is to maintain backwards compatibility because the custom dialer is replaced by
|
||||
// the default dialer in grpc-go.
|
||||
// https://github.com/fullstorydev/grpcurl/pull/480
|
||||
target = "unix://" + target
|
||||
}
|
||||
var creds credentials.TransportCredentials
|
||||
if !*plaintext {
|
||||
var err error
|
||||
creds, err = grpcurl.ClientTransportCredentials(*insecure, *cacert, *cert, *key)
|
||||
if err != nil {
|
||||
fail(err, "Failed to configure transport credentials")
|
||||
if *plaintext {
|
||||
if *authority != "" {
|
||||
opts = append(opts, grpc.WithAuthority(*authority))
|
||||
}
|
||||
} else if *usealts {
|
||||
clientOptions := alts.DefaultClientOptions()
|
||||
if len(altsTargetServiceAccounts) > 0 {
|
||||
clientOptions.TargetServiceAccounts = altsTargetServiceAccounts
|
||||
}
|
||||
if *altsHandshakerServiceAddress != "" {
|
||||
clientOptions.HandshakerServiceAddress = *altsHandshakerServiceAddress
|
||||
}
|
||||
creds = alts.NewClientCreds(clientOptions)
|
||||
} else if usetls {
|
||||
tlsTiming := dialTiming.Child("TLS Setup")
|
||||
defer tlsTiming.Done()
|
||||
|
||||
tlsConf, err := grpcurl.ClientTLSConfig(*insecure, *cacert, *cert, *key)
|
||||
if err != nil {
|
||||
fail(err, "Failed to create TLS config")
|
||||
}
|
||||
|
||||
sslKeylogFile := os.Getenv("SSLKEYLOGFILE")
|
||||
if sslKeylogFile != "" {
|
||||
w, err := os.OpenFile(sslKeylogFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
fail(err, "Could not open SSLKEYLOGFILE %s", sslKeylogFile)
|
||||
}
|
||||
tlsConf.KeyLogWriter = w
|
||||
}
|
||||
|
||||
creds = credentials.NewTLS(tlsConf)
|
||||
|
||||
// can use either -servername or -authority; but not both
|
||||
if *serverName != "" && *authority != "" {
|
||||
|
|
@ -403,18 +539,25 @@ func main() {
|
|||
}
|
||||
|
||||
if overrideName != "" {
|
||||
if err := creds.OverrideServerName(overrideName); err != nil {
|
||||
fail(err, "Failed to override server name as %q", overrideName)
|
||||
}
|
||||
opts = append(opts, grpc.WithAuthority(overrideName))
|
||||
}
|
||||
} else if *authority != "" {
|
||||
opts = append(opts, grpc.WithAuthority(*authority))
|
||||
tlsTiming.Done()
|
||||
} else {
|
||||
panic("Should have defaulted to use TLS.")
|
||||
}
|
||||
network := "tcp"
|
||||
if isUnixSocket != nil && isUnixSocket() {
|
||||
network = "unix"
|
||||
|
||||
grpcurlUA := "grpcurl/" + version
|
||||
if version == noVersion {
|
||||
grpcurlUA = "grpcurl/dev-build (no version set)"
|
||||
}
|
||||
cc, err := grpcurl.BlockingDial(ctx, network, target, creds, opts...)
|
||||
if *userAgent != "" {
|
||||
grpcurlUA = *userAgent + " " + grpcurlUA
|
||||
}
|
||||
opts = append(opts, grpc.WithUserAgent(grpcurlUA))
|
||||
|
||||
blockingDialTiming := dialTiming.Child("BlockingDial")
|
||||
defer blockingDialTiming.Done()
|
||||
cc, err := grpcurl.BlockingDial(ctx, "", target, creds, opts...)
|
||||
if err != nil {
|
||||
fail(err, "Failed to dial target host %q", target)
|
||||
}
|
||||
|
|
@ -465,7 +608,8 @@ func main() {
|
|||
md := grpcurl.MetadataFromHeaders(append(addlHeaders, reflHeaders...))
|
||||
refCtx := metadata.NewOutgoingContext(ctx, md)
|
||||
cc = dial()
|
||||
refClient = grpcreflect.NewClient(refCtx, reflectpb.NewServerReflectionClient(cc))
|
||||
refClient = grpcreflect.NewClientAuto(refCtx, cc)
|
||||
refClient.AllowMissingFileDescriptors()
|
||||
reflSource := grpcurl.DescriptorSourceFromServer(ctx, refClient)
|
||||
if fileSource != nil {
|
||||
descSource = compositeSource{reflSource, fileSource}
|
||||
|
|
@ -510,6 +654,9 @@ func main() {
|
|||
if err := writeProtoset(descSource, svcs...); err != nil {
|
||||
fail(err, "Failed to write protoset to %s", *protosetOut)
|
||||
}
|
||||
if err := writeProtos(descSource, svcs...); err != nil {
|
||||
fail(err, "Failed to write protos to %s", *protoOut)
|
||||
}
|
||||
} else {
|
||||
methods, err := grpcurl.ListMethods(descSource, symbol)
|
||||
if err != nil {
|
||||
|
|
@ -525,6 +672,9 @@ func main() {
|
|||
if err := writeProtoset(descSource, symbol); err != nil {
|
||||
fail(err, "Failed to write protoset to %s", *protosetOut)
|
||||
}
|
||||
if err := writeProtos(descSource, symbol); err != nil {
|
||||
fail(err, "Failed to write protos to %s", *protoOut)
|
||||
}
|
||||
}
|
||||
|
||||
} else if describe {
|
||||
|
|
@ -571,7 +721,7 @@ func main() {
|
|||
} else {
|
||||
// see if it's a group
|
||||
for _, f := range parent.GetFields() {
|
||||
if f.GetType() == descpb.FieldDescriptorProto_TYPE_GROUP && f.GetMessageType() == d {
|
||||
if f.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP && f.GetMessageType() == d {
|
||||
// found it: describe the map field instead
|
||||
elementType = "the type of a group field"
|
||||
dsc = f
|
||||
|
|
@ -582,7 +732,7 @@ func main() {
|
|||
}
|
||||
case *desc.FieldDescriptor:
|
||||
elementType = "a field"
|
||||
if d.GetType() == descpb.FieldDescriptorProto_TYPE_GROUP {
|
||||
if d.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP {
|
||||
elementType = "a group field"
|
||||
} else if d.IsExtension() {
|
||||
elementType = "an extension"
|
||||
|
|
@ -613,7 +763,8 @@ func main() {
|
|||
// for messages, also show a template in JSON, to make it easier to
|
||||
// create a request to invoke an RPC
|
||||
tmpl := grpcurl.MakeTemplate(dsc)
|
||||
_, formatter, err := grpcurl.RequestParserAndFormatterFor(grpcurl.Format(*format), descSource, true, false, nil)
|
||||
options := grpcurl.FormatOptions{EmitJSONDefaultFields: true}
|
||||
_, formatter, err := grpcurl.RequestParserAndFormatter(grpcurl.Format(*format), descSource, nil, options)
|
||||
if err != nil {
|
||||
fail(err, "Failed to construct formatter for %q", *format)
|
||||
}
|
||||
|
|
@ -628,6 +779,9 @@ func main() {
|
|||
if err := writeProtoset(descSource, symbols...); err != nil {
|
||||
fail(err, "Failed to write protoset to %s", *protosetOut)
|
||||
}
|
||||
if err := writeProtos(descSource, symbol); err != nil {
|
||||
fail(err, "Failed to write protos to %s", *protoOut)
|
||||
}
|
||||
|
||||
} else {
|
||||
// Invoke an RPC
|
||||
|
|
@ -644,16 +798,31 @@ func main() {
|
|||
// if not verbose output, then also include record delimiters
|
||||
// between each message, so output could potentially be piped
|
||||
// to another grpcurl process
|
||||
includeSeparators := !*verbose
|
||||
rf, formatter, err := grpcurl.RequestParserAndFormatterFor(grpcurl.Format(*format), descSource, *emitDefaults, includeSeparators, in)
|
||||
includeSeparators := verbosityLevel == 0
|
||||
options := grpcurl.FormatOptions{
|
||||
EmitJSONDefaultFields: *emitDefaults,
|
||||
IncludeTextSeparator: includeSeparators,
|
||||
AllowUnknownFields: *allowUnknownFields,
|
||||
}
|
||||
rf, formatter, err := grpcurl.RequestParserAndFormatter(grpcurl.Format(*format), descSource, in, options)
|
||||
if err != nil {
|
||||
fail(err, "Failed to construct request parser and formatter for %q", *format)
|
||||
}
|
||||
h := grpcurl.NewDefaultEventHandler(os.Stdout, descSource, formatter, *verbose)
|
||||
h := &grpcurl.DefaultEventHandler{
|
||||
Out: os.Stdout,
|
||||
Formatter: formatter,
|
||||
VerbosityLevel: verbosityLevel,
|
||||
}
|
||||
|
||||
invokeTiming := rootTiming.Child("InvokeRPC")
|
||||
err = grpcurl.InvokeRPC(ctx, descSource, cc, symbol, append(addlHeaders, rpcHeaders...), h, rf.Next)
|
||||
invokeTiming.Done()
|
||||
if err != nil {
|
||||
fail(err, "Error invoking method %q", symbol)
|
||||
if errStatus, ok := status.FromError(err); ok && *formatError {
|
||||
h.Status = errStatus
|
||||
} else {
|
||||
fail(err, "Error invoking method %q", symbol)
|
||||
}
|
||||
}
|
||||
reqSuffix := ""
|
||||
respSuffix := ""
|
||||
|
|
@ -664,7 +833,7 @@ func main() {
|
|||
if h.NumResponses != 1 {
|
||||
respSuffix = "s"
|
||||
}
|
||||
if *verbose {
|
||||
if verbosityLevel > 0 {
|
||||
fmt.Printf("Sent %d request%s and received %d response%s\n", reqCount, reqSuffix, h.NumResponses, respSuffix)
|
||||
}
|
||||
if h.Status.Code() != codes.OK {
|
||||
|
|
@ -678,6 +847,17 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
func dumpTiming(td *timingData, lvl int) {
|
||||
var ind strings.Builder
|
||||
for x := 0; x < lvl; x++ {
|
||||
ind.WriteString(" ")
|
||||
}
|
||||
fmt.Printf("%s%s: %s\n", ind.String(), td.Title, td.Value)
|
||||
for _, sd := range td.Sub {
|
||||
dumpTiming(sd, lvl+1)
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, `Usage:
|
||||
%s [flags] [address] [list|describe] [symbol]
|
||||
|
|
@ -725,7 +905,7 @@ func prettify(docString string) string {
|
|||
j++
|
||||
}
|
||||
|
||||
return strings.Join(parts[:j], "\n"+indent())
|
||||
return strings.Join(parts[:j], "\n")
|
||||
}
|
||||
|
||||
func warn(msg string, args ...interface{}) {
|
||||
|
|
@ -761,6 +941,13 @@ func writeProtoset(descSource grpcurl.DescriptorSource, symbols ...string) error
|
|||
return grpcurl.WriteProtoset(f, descSource, symbols...)
|
||||
}
|
||||
|
||||
func writeProtos(descSource grpcurl.DescriptorSource, symbols ...string) error {
|
||||
if *protoOut == "" {
|
||||
return nil
|
||||
}
|
||||
return grpcurl.WriteProtoFiles(*protoOut, descSource, symbols...)
|
||||
}
|
||||
|
||||
type optionalBoolFlag struct {
|
||||
set, val bool
|
||||
}
|
||||
|
|
@ -785,3 +972,12 @@ func (f *optionalBoolFlag) Set(s string) error {
|
|||
func (f *optionalBoolFlag) IsBoolFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func floatSecondsToDuration(seconds float64) time.Duration {
|
||||
durationFloat := seconds * float64(time.Second)
|
||||
if durationFloat > math.MaxInt64 {
|
||||
// Avoid overflow
|
||||
return math.MaxInt64
|
||||
}
|
||||
return time.Duration(durationFloat)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||
|
||||
package main
|
||||
|
||||
|
|
|
|||
123
desc_source.go
123
desc_source.go
|
|
@ -1,21 +1,23 @@
|
|||
package grpcurl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/desc/protoparse"
|
||||
"github.com/jhump/protoreflect/dynamic"
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import these because some of their types appear in exported API
|
||||
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/desc/protoparse" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/desc/protoprint"
|
||||
"github.com/jhump/protoreflect/dynamic" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/grpcreflect"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
// ErrReflectionNotSupported is returned by DescriptorSource operations that
|
||||
|
|
@ -39,13 +41,13 @@ type DescriptorSource interface {
|
|||
// DescriptorSourceFromProtoSets creates a DescriptorSource that is backed by the named files, whose contents
|
||||
// are encoded FileDescriptorSet protos.
|
||||
func DescriptorSourceFromProtoSets(fileNames ...string) (DescriptorSource, error) {
|
||||
files := &descpb.FileDescriptorSet{}
|
||||
files := &descriptorpb.FileDescriptorSet{}
|
||||
for _, fileName := range fileNames {
|
||||
b, err := ioutil.ReadFile(fileName)
|
||||
b, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not load protoset file %q: %v", fileName, err)
|
||||
}
|
||||
var fs descpb.FileDescriptorSet
|
||||
var fs descriptorpb.FileDescriptorSet
|
||||
err = proto.Unmarshal(b, &fs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse contents of protoset file %q: %v", fileName, err)
|
||||
|
|
@ -76,8 +78,8 @@ func DescriptorSourceFromProtoFiles(importPaths []string, fileNames ...string) (
|
|||
}
|
||||
|
||||
// DescriptorSourceFromFileDescriptorSet creates a DescriptorSource that is backed by the FileDescriptorSet.
|
||||
func DescriptorSourceFromFileDescriptorSet(files *descpb.FileDescriptorSet) (DescriptorSource, error) {
|
||||
unresolved := map[string]*descpb.FileDescriptorProto{}
|
||||
func DescriptorSourceFromFileDescriptorSet(files *descriptorpb.FileDescriptorSet) (DescriptorSource, error) {
|
||||
unresolved := map[string]*descriptorpb.FileDescriptorProto{}
|
||||
for _, fd := range files.File {
|
||||
unresolved[fd.GetName()] = fd
|
||||
}
|
||||
|
|
@ -91,7 +93,7 @@ func DescriptorSourceFromFileDescriptorSet(files *descpb.FileDescriptorSet) (Des
|
|||
return &fileSource{files: resolved}, nil
|
||||
}
|
||||
|
||||
func resolveFileDescriptor(unresolved map[string]*descpb.FileDescriptorProto, resolved map[string]*desc.FileDescriptor, filename string) (*desc.FileDescriptor, error) {
|
||||
func resolveFileDescriptor(unresolved map[string]*descriptorpb.FileDescriptorProto, resolved map[string]*desc.FileDescriptor, filename string) (*desc.FileDescriptor, error) {
|
||||
if r, ok := resolved[filename]; ok {
|
||||
return r, nil
|
||||
}
|
||||
|
|
@ -258,29 +260,19 @@ func reflectionSupport(err error) error {
|
|||
// given output. The output will include descriptors for all files in which the
|
||||
// symbols are defined as well as their transitive dependencies.
|
||||
func WriteProtoset(out io.Writer, descSource DescriptorSource, symbols ...string) error {
|
||||
// compute set of file descriptors
|
||||
filenames := make([]string, 0, len(symbols))
|
||||
fds := make(map[string]*desc.FileDescriptor, len(symbols))
|
||||
for _, sym := range symbols {
|
||||
d, err := descSource.FindSymbol(sym)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find descriptor for %q: %v", sym, err)
|
||||
}
|
||||
fd := d.GetFile()
|
||||
if _, ok := fds[fd.GetName()]; !ok {
|
||||
fds[fd.GetName()] = fd
|
||||
filenames = append(filenames, fd.GetName())
|
||||
}
|
||||
filenames, fds, err := getFileDescriptors(symbols, descSource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// now expand that to include transitive dependencies in topologically sorted
|
||||
// order (such that file always appears after its dependencies)
|
||||
expandedFiles := make(map[string]struct{}, len(fds))
|
||||
allFilesSlice := make([]*descpb.FileDescriptorProto, 0, len(fds))
|
||||
allFilesSlice := make([]*descriptorpb.FileDescriptorProto, 0, len(fds))
|
||||
for _, filename := range filenames {
|
||||
allFilesSlice = addFilesToSet(allFilesSlice, expandedFiles, fds[filename])
|
||||
}
|
||||
// now we can serialize to file
|
||||
b, err := proto.Marshal(&descpb.FileDescriptorSet{File: allFilesSlice})
|
||||
b, err := proto.Marshal(&descriptorpb.FileDescriptorSet{File: allFilesSlice})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize file descriptor set: %v", err)
|
||||
}
|
||||
|
|
@ -290,7 +282,7 @@ func WriteProtoset(out io.Writer, descSource DescriptorSource, symbols ...string
|
|||
return nil
|
||||
}
|
||||
|
||||
func addFilesToSet(allFiles []*descpb.FileDescriptorProto, expanded map[string]struct{}, fd *desc.FileDescriptor) []*descpb.FileDescriptorProto {
|
||||
func addFilesToSet(allFiles []*descriptorpb.FileDescriptorProto, expanded map[string]struct{}, fd *desc.FileDescriptor) []*descriptorpb.FileDescriptorProto {
|
||||
if _, ok := expanded[fd.GetName()]; ok {
|
||||
// already seen this one
|
||||
return allFiles
|
||||
|
|
@ -302,3 +294,76 @@ func addFilesToSet(allFiles []*descpb.FileDescriptorProto, expanded map[string]s
|
|||
}
|
||||
return append(allFiles, fd.AsFileDescriptorProto())
|
||||
}
|
||||
|
||||
// WriteProtoFiles will use the given descriptor source to resolve all the given
|
||||
// symbols and write proto files with their definitions to the given output directory.
|
||||
func WriteProtoFiles(outProtoDirPath string, descSource DescriptorSource, symbols ...string) error {
|
||||
filenames, fds, err := getFileDescriptors(symbols, descSource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// now expand that to include transitive dependencies in topologically sorted
|
||||
// order (such that file always appears after its dependencies)
|
||||
expandedFiles := make(map[string]struct{}, len(fds))
|
||||
allFileDescriptors := make([]*desc.FileDescriptor, 0, len(fds))
|
||||
for _, filename := range filenames {
|
||||
allFileDescriptors = addFilesToFileDescriptorList(allFileDescriptors, expandedFiles, fds[filename])
|
||||
}
|
||||
pr := protoprint.Printer{}
|
||||
// now we can serialize to files
|
||||
for i := range allFileDescriptors {
|
||||
if err := writeProtoFile(outProtoDirPath, allFileDescriptors[i], &pr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeProtoFile(outProtoDirPath string, fd *desc.FileDescriptor, pr *protoprint.Printer) error {
|
||||
outFile := filepath.Join(outProtoDirPath, fd.GetFullyQualifiedName())
|
||||
outDir := filepath.Dir(outFile)
|
||||
if err := os.MkdirAll(outDir, 0777); err != nil {
|
||||
return fmt.Errorf("failed to create directory %q: %w", outDir, err)
|
||||
}
|
||||
|
||||
f, err := os.Create(outFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create proto file %q: %w", outFile, err)
|
||||
}
|
||||
defer f.Close()
|
||||
if err := pr.PrintProtoFile(fd, f); err != nil {
|
||||
return fmt.Errorf("failed to write proto file %q: %w", outFile, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFileDescriptors(symbols []string, descSource DescriptorSource) ([]string, map[string]*desc.FileDescriptor, error) {
|
||||
// compute set of file descriptors
|
||||
filenames := make([]string, 0, len(symbols))
|
||||
fds := make(map[string]*desc.FileDescriptor, len(symbols))
|
||||
for _, sym := range symbols {
|
||||
d, err := descSource.FindSymbol(sym)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to find descriptor for %q: %v", sym, err)
|
||||
}
|
||||
fd := d.GetFile()
|
||||
if _, ok := fds[fd.GetName()]; !ok {
|
||||
fds[fd.GetName()] = fd
|
||||
filenames = append(filenames, fd.GetName())
|
||||
}
|
||||
}
|
||||
return filenames, fds, nil
|
||||
}
|
||||
|
||||
func addFilesToFileDescriptorList(allFiles []*desc.FileDescriptor, expanded map[string]struct{}, fd *desc.FileDescriptor) []*desc.FileDescriptor {
|
||||
if _, ok := expanded[fd.GetName()]; ok {
|
||||
// already seen this one
|
||||
return allFiles
|
||||
}
|
||||
expanded[fd.GetName()] = struct{}{}
|
||||
// add all dependencies first
|
||||
for _, dep := range fd.GetDependencies() {
|
||||
allFiles = addFilesToFileDescriptorList(allFiles, expanded, dep)
|
||||
}
|
||||
return append(allFiles, fd)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,24 +2,24 @@ package grpcurl
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
func TestWriteProtoset(t *testing.T) {
|
||||
exampleProtoset, err := loadProtoset("./testing/example.protoset")
|
||||
exampleProtoset, err := loadProtoset("./internal/testing/example.protoset")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load example.protoset: %v", err)
|
||||
}
|
||||
testProtoset, err := loadProtoset("./testing/test.protoset")
|
||||
testProtoset, err := loadProtoset("./internal/testing/test.protoset")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load test.protoset: %v", err)
|
||||
}
|
||||
|
||||
mergedProtoset := &descriptor.FileDescriptorSet{
|
||||
mergedProtoset := &descriptorpb.FileDescriptorSet{
|
||||
File: append(exampleProtoset.File, testProtoset.File...),
|
||||
}
|
||||
|
||||
|
|
@ -29,29 +29,29 @@ func TestWriteProtoset(t *testing.T) {
|
|||
}
|
||||
|
||||
checkWriteProtoset(t, descSrc, exampleProtoset, "TestService")
|
||||
checkWriteProtoset(t, descSrc, testProtoset, "grpc.testing.TestService")
|
||||
checkWriteProtoset(t, descSrc, mergedProtoset, "TestService", "grpc.testing.TestService")
|
||||
checkWriteProtoset(t, descSrc, testProtoset, "testing.TestService")
|
||||
checkWriteProtoset(t, descSrc, mergedProtoset, "TestService", "testing.TestService")
|
||||
}
|
||||
|
||||
func loadProtoset(path string) (*descriptor.FileDescriptorSet, error) {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
func loadProtoset(path string) (*descriptorpb.FileDescriptorSet, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var protoset descriptor.FileDescriptorSet
|
||||
var protoset descriptorpb.FileDescriptorSet
|
||||
if err := proto.Unmarshal(b, &protoset); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &protoset, nil
|
||||
}
|
||||
|
||||
func checkWriteProtoset(t *testing.T, descSrc DescriptorSource, protoset *descriptor.FileDescriptorSet, symbols ...string) {
|
||||
func checkWriteProtoset(t *testing.T, descSrc DescriptorSource, protoset *descriptorpb.FileDescriptorSet, symbols ...string) {
|
||||
var buf bytes.Buffer
|
||||
if err := WriteProtoset(&buf, descSrc, symbols...); err != nil {
|
||||
t.Fatalf("failed to write protoset: %v", err)
|
||||
}
|
||||
|
||||
var result descriptor.FileDescriptorSet
|
||||
var result descriptorpb.FileDescriptorSet
|
||||
if err := proto.Unmarshal(buf.Bytes(), &result); err != nil {
|
||||
t.Fatalf("failed to unmarshal written protoset: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
if [[ -z "$PROTOC_VERSION" ]]; then
|
||||
echo "Set PROTOC_VERSION env var to indicate the version to download" >&2
|
||||
exit 1
|
||||
fi
|
||||
PROTOC_OS="$(uname -s)"
|
||||
PROTOC_ARCH="$(uname -m)"
|
||||
case "${PROTOC_OS}" in
|
||||
Darwin) PROTOC_OS="osx" ;;
|
||||
Linux) PROTOC_OS="linux" ;;
|
||||
*)
|
||||
echo "Invalid value for uname -s: ${PROTOC_OS}" >&2
|
||||
exit 1
|
||||
esac
|
||||
|
||||
# This is for macs with M1 chips. Precompiled binaries for osx/amd64 are not available for download, so for that case
|
||||
# we download the x86_64 version instead. This will work as long as rosetta2 is installed.
|
||||
if [ "$PROTOC_OS" = "osx" ] && [ "$PROTOC_ARCH" = "arm64" ]; then
|
||||
PROTOC_ARCH="x86_64"
|
||||
fi
|
||||
|
||||
PROTOC="${PWD}/.tmp/protoc/bin/protoc"
|
||||
|
||||
if [[ "$(${PROTOC} --version 2>/dev/null)" != "libprotoc 3.${PROTOC_VERSION}" ]]; then
|
||||
rm -rf ./.tmp/protoc
|
||||
mkdir -p .tmp/protoc
|
||||
curl -L "https://github.com/google/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${PROTOC_OS}-${PROTOC_ARCH}.zip" > .tmp/protoc/protoc.zip
|
||||
pushd ./.tmp/protoc && unzip protoc.zip && popd
|
||||
fi
|
||||
|
||||
169
format.go
169
format.go
|
|
@ -11,10 +11,10 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/dynamic"
|
||||
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 we have to import these because some of their types appear in exported API
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/dynamic" //lint:ignore SA1019 same as above
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
|
|
@ -55,6 +55,15 @@ func NewJSONRequestParser(in io.Reader, resolver jsonpb.AnyResolver) RequestPars
|
|||
}
|
||||
}
|
||||
|
||||
// NewJSONRequestParserWithUnmarshaler is like NewJSONRequestParser but
|
||||
// accepts a protobuf jsonpb.Unmarshaler instead of jsonpb.AnyResolver.
|
||||
func NewJSONRequestParserWithUnmarshaler(in io.Reader, unmarshaler jsonpb.Unmarshaler) RequestParser {
|
||||
return &jsonRequestParser{
|
||||
dec: json.NewDecoder(in),
|
||||
unmarshaler: unmarshaler,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *jsonRequestParser) Next(m proto.Message) error {
|
||||
var msg json.RawMessage
|
||||
if err := f.dec.Decode(&msg); err != nil {
|
||||
|
|
@ -127,10 +136,25 @@ type Formatter func(proto.Message) (string, error)
|
|||
func NewJSONFormatter(emitDefaults bool, resolver jsonpb.AnyResolver) Formatter {
|
||||
marshaler := jsonpb.Marshaler{
|
||||
EmitDefaults: emitDefaults,
|
||||
Indent: " ",
|
||||
AnyResolver: resolver,
|
||||
}
|
||||
return marshaler.MarshalToString
|
||||
// Workaround for indentation issue in jsonpb with Any messages.
|
||||
// Bug was originally fixed in https://github.com/golang/protobuf/pull/834
|
||||
// but later re-introduced before the module was deprecated and frozen.
|
||||
// If jsonpb is ever replaced with google.golang.org/protobuf/encoding/protojson
|
||||
// this workaround will no longer be needed.
|
||||
formatter := func(message proto.Message) (string, error) {
|
||||
output, err := marshaler.MarshalToString(message)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := json.Indent(&buf, []byte(output), "", " "); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
return formatter
|
||||
}
|
||||
|
||||
// NewTextFormatter returns a formatter that returns strings in the protobuf
|
||||
|
|
@ -188,10 +212,20 @@ func (tf *textFormatter) format(m proto.Message) (string, error) {
|
|||
return str, nil
|
||||
}
|
||||
|
||||
// Format of request data. The allowed values are 'json' or 'text'.
|
||||
type Format string
|
||||
|
||||
const (
|
||||
// FormatJSON specifies input data in JSON format. Multiple request values
|
||||
// may be concatenated (messages with a JSON representation other than
|
||||
// object must be separated by whitespace, such as a newline)
|
||||
FormatJSON = Format("json")
|
||||
|
||||
// FormatText specifies input data must be in the protobuf text format.
|
||||
// Multiple request values must be separated by the "record separator"
|
||||
// ASCII character: 0x1E. The stream should not end in a record separator.
|
||||
// If it does, it will be interpreted as a final, blank message after the
|
||||
// separator.
|
||||
FormatText = Format("text")
|
||||
)
|
||||
|
||||
|
|
@ -255,11 +289,11 @@ func (r *anyResolver) Resolve(typeUrl string) (proto.Message, error) {
|
|||
if !ok {
|
||||
return nil, fmt.Errorf("unknown message: %s", typeUrl)
|
||||
}
|
||||
// populate any extensions for this message, too
|
||||
if exts, err := r.source.AllExtensionsForType(mname); err != nil {
|
||||
return nil, err
|
||||
} else if err := r.er.AddExtension(exts...); err != nil {
|
||||
return nil, err
|
||||
// populate any extensions for this message, too (if there are any)
|
||||
if exts, err := r.source.AllExtensionsForType(mname); err == nil {
|
||||
if err := r.er.AddExtension(exts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if r.mf == nil {
|
||||
|
|
@ -296,6 +330,7 @@ func (r anyResolverWithFallback) Resolve(typeUrl string) (proto.Message, error)
|
|||
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
|
||||
mname = mname[slash+1:]
|
||||
}
|
||||
//lint:ignore SA1019 new non-deprecated API requires other code changes; deferring...
|
||||
mt := proto.MessageType(mname)
|
||||
if mt != nil {
|
||||
return reflect.New(mt.Elem()).Interface().(proto.Message), nil
|
||||
|
|
@ -342,31 +377,70 @@ func (a *unknownAny) ProtoMessage() {
|
|||
|
||||
var _ proto.Message = (*unknownAny)(nil)
|
||||
|
||||
// FormatOptions is a set of flags that are passed to a JSON or text formatter.
|
||||
type FormatOptions struct {
|
||||
// EmitJSONDefaultFields flag, when true, includes empty/default values in the output.
|
||||
// FormatJSON only flag.
|
||||
EmitJSONDefaultFields bool
|
||||
|
||||
// AllowUnknownFields is an option for the parser. When true,
|
||||
// it accepts input which includes unknown fields. These unknown fields
|
||||
// are skipped instead of returning an error.
|
||||
// FormatJSON only flag.
|
||||
AllowUnknownFields bool
|
||||
|
||||
// IncludeTextSeparator is true then, when invoked to format multiple messages,
|
||||
// all messages after the first one will be prefixed with the
|
||||
// ASCII 'Record Separator' character (0x1E).
|
||||
// It might be useful when the output is piped to another grpcurl process.
|
||||
// FormatText only flag.
|
||||
IncludeTextSeparator bool
|
||||
}
|
||||
|
||||
// RequestParserAndFormatter returns a request parser and formatter for the
|
||||
// given format. The given descriptor source may be used for parsing message
|
||||
// data (if needed by the format).
|
||||
// It accepts a set of options. The field EmitJSONDefaultFields and IncludeTextSeparator
|
||||
// are options for JSON and protobuf text formats, respectively. The AllowUnknownFields field
|
||||
// is a JSON-only format flag.
|
||||
// Requests will be parsed from the given in.
|
||||
func RequestParserAndFormatter(format Format, descSource DescriptorSource, in io.Reader, opts FormatOptions) (RequestParser, Formatter, error) {
|
||||
switch format {
|
||||
case FormatJSON:
|
||||
resolver := AnyResolverFromDescriptorSource(descSource)
|
||||
unmarshaler := jsonpb.Unmarshaler{AnyResolver: resolver, AllowUnknownFields: opts.AllowUnknownFields}
|
||||
return NewJSONRequestParserWithUnmarshaler(in, unmarshaler), NewJSONFormatter(opts.EmitJSONDefaultFields, anyResolverWithFallback{AnyResolver: resolver}), nil
|
||||
case FormatText:
|
||||
return NewTextRequestParser(in), NewTextFormatter(opts.IncludeTextSeparator), nil
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("unknown format: %s", format)
|
||||
}
|
||||
}
|
||||
|
||||
// RequestParserAndFormatterFor returns a request parser and formatter for the
|
||||
// given format. The given descriptor source may be used for parsing message
|
||||
// data (if needed by the format). The flags emitJSONDefaultFields and
|
||||
// includeTextSeparator are options for JSON and protobuf text formats,
|
||||
// respectively. Requests will be parsed from the given in.
|
||||
// This function is deprecated. Please use RequestParserAndFormatter instead.
|
||||
// DEPRECATED
|
||||
func RequestParserAndFormatterFor(format Format, descSource DescriptorSource, emitJSONDefaultFields, includeTextSeparator bool, in io.Reader) (RequestParser, Formatter, error) {
|
||||
switch format {
|
||||
case FormatJSON:
|
||||
resolver := AnyResolverFromDescriptorSource(descSource)
|
||||
return NewJSONRequestParser(in, resolver), NewJSONFormatter(emitJSONDefaultFields, anyResolverWithFallback{AnyResolver: resolver}), nil
|
||||
case FormatText:
|
||||
return NewTextRequestParser(in), NewTextFormatter(includeTextSeparator), nil
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("unknown format: %s", format)
|
||||
}
|
||||
return RequestParserAndFormatter(format, descSource, in, FormatOptions{
|
||||
EmitJSONDefaultFields: emitJSONDefaultFields,
|
||||
IncludeTextSeparator: includeTextSeparator,
|
||||
})
|
||||
}
|
||||
|
||||
// DefaultEventHandler logs events to a writer. This is not thread-safe, but is
|
||||
// safe for use with InvokeRPC as long as NumResponses and Status are not read
|
||||
// until the call to InvokeRPC completes.
|
||||
type DefaultEventHandler struct {
|
||||
out io.Writer
|
||||
descSource DescriptorSource
|
||||
formatter func(proto.Message) (string, error)
|
||||
verbose bool
|
||||
Out io.Writer
|
||||
Formatter Formatter
|
||||
// 0 = default
|
||||
// 1 = verbose
|
||||
// 2 = very verbose
|
||||
VerbosityLevel int
|
||||
|
||||
// NumResponses is the number of responses that have been received.
|
||||
NumResponses int
|
||||
|
|
@ -378,54 +452,65 @@ type DefaultEventHandler struct {
|
|||
// NewDefaultEventHandler returns an InvocationEventHandler that logs events to
|
||||
// the given output. If verbose is true, all events are logged. Otherwise, only
|
||||
// response messages are logged.
|
||||
//
|
||||
// Deprecated: NewDefaultEventHandler exists for compatibility.
|
||||
// It doesn't allow fine control over the `VerbosityLevel`
|
||||
// and provides only 0 and 1 options (which corresponds to the `verbose` argument).
|
||||
// Use DefaultEventHandler{} initializer directly.
|
||||
func NewDefaultEventHandler(out io.Writer, descSource DescriptorSource, formatter Formatter, verbose bool) *DefaultEventHandler {
|
||||
verbosityLevel := 0
|
||||
if verbose {
|
||||
verbosityLevel = 1
|
||||
}
|
||||
return &DefaultEventHandler{
|
||||
out: out,
|
||||
descSource: descSource,
|
||||
formatter: formatter,
|
||||
verbose: verbose,
|
||||
Out: out,
|
||||
Formatter: formatter,
|
||||
VerbosityLevel: verbosityLevel,
|
||||
}
|
||||
}
|
||||
|
||||
var _ InvocationEventHandler = (*DefaultEventHandler)(nil)
|
||||
|
||||
func (h *DefaultEventHandler) OnResolveMethod(md *desc.MethodDescriptor) {
|
||||
if h.verbose {
|
||||
txt, err := GetDescriptorText(md, h.descSource)
|
||||
if h.VerbosityLevel > 0 {
|
||||
txt, err := GetDescriptorText(md, nil)
|
||||
if err == nil {
|
||||
fmt.Fprintf(h.out, "\nResolved method descriptor:\n%s\n", txt)
|
||||
fmt.Fprintf(h.Out, "\nResolved method descriptor:\n%s\n", txt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *DefaultEventHandler) OnSendHeaders(md metadata.MD) {
|
||||
if h.verbose {
|
||||
fmt.Fprintf(h.out, "\nRequest metadata to send:\n%s\n", MetadataToString(md))
|
||||
if h.VerbosityLevel > 0 {
|
||||
fmt.Fprintf(h.Out, "\nRequest metadata to send:\n%s\n", MetadataToString(md))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *DefaultEventHandler) OnReceiveHeaders(md metadata.MD) {
|
||||
if h.verbose {
|
||||
fmt.Fprintf(h.out, "\nResponse headers received:\n%s\n", MetadataToString(md))
|
||||
if h.VerbosityLevel > 0 {
|
||||
fmt.Fprintf(h.Out, "\nResponse headers received:\n%s\n", MetadataToString(md))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *DefaultEventHandler) OnReceiveResponse(resp proto.Message) {
|
||||
h.NumResponses++
|
||||
if h.verbose {
|
||||
fmt.Fprint(h.out, "\nResponse contents:\n")
|
||||
if h.VerbosityLevel > 1 {
|
||||
fmt.Fprintf(h.Out, "\nEstimated response size: %d bytes\n", proto.Size(resp))
|
||||
}
|
||||
if respStr, err := h.formatter(resp); err != nil {
|
||||
fmt.Fprintf(h.out, "Failed to format response message %d: %v\n", h.NumResponses, err)
|
||||
if h.VerbosityLevel > 0 {
|
||||
fmt.Fprint(h.Out, "\nResponse contents:\n")
|
||||
}
|
||||
if respStr, err := h.Formatter(resp); err != nil {
|
||||
fmt.Fprintf(h.Out, "Failed to format response message %d: %v\n", h.NumResponses, err)
|
||||
} else {
|
||||
fmt.Fprintln(h.out, respStr)
|
||||
fmt.Fprintln(h.Out, respStr)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *DefaultEventHandler) OnReceiveTrailers(stat *status.Status, md metadata.MD) {
|
||||
h.Status = stat
|
||||
if h.verbose {
|
||||
fmt.Fprintf(h.out, "\nResponse trailers received:\n%s\n", MetadataToString(md))
|
||||
if h.VerbosityLevel > 0 {
|
||||
fmt.Fprintf(h.Out, "\nResponse trailers received:\n%s\n", MetadataToString(md))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes/struct"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 we have to import these because some of their types appear in exported API
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
func TestRequestParser(t *testing.T) {
|
||||
source, err := DescriptorSourceFromProtoSets("testing/example.protoset")
|
||||
source, err := DescriptorSourceFromProtoSets("internal/testing/example.protoset")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create descriptor source: %v", err)
|
||||
}
|
||||
|
|
@ -69,7 +69,7 @@ func TestRequestParser(t *testing.T) {
|
|||
|
||||
for i, tc := range testCases {
|
||||
name := fmt.Sprintf("#%d, %s, %d message(s)", i+1, tc.format, len(tc.expectedOutput))
|
||||
rf, _, err := RequestParserAndFormatterFor(tc.format, source, false, false, strings.NewReader(tc.input))
|
||||
rf, _, err := RequestParserAndFormatter(tc.format, source, strings.NewReader(tc.input), FormatOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create parser and formatter: %v", err)
|
||||
continue
|
||||
|
|
@ -97,7 +97,7 @@ func TestRequestParser(t *testing.T) {
|
|||
// Handler prints response data (and headers/trailers in verbose mode).
|
||||
// This verifies that we get the right output in both JSON and proto text modes.
|
||||
func TestHandler(t *testing.T) {
|
||||
source, err := DescriptorSourceFromProtoSets("testing/example.protoset")
|
||||
source, err := DescriptorSourceFromProtoSets("internal/testing/example.protoset")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create descriptor source: %v", err)
|
||||
}
|
||||
|
|
@ -120,20 +120,26 @@ func TestHandler(t *testing.T) {
|
|||
|
||||
for _, format := range []Format{FormatJSON, FormatText} {
|
||||
for _, numMessages := range []int{1, 3} {
|
||||
for _, verbose := range []bool{true, false} {
|
||||
for verbosityLevel := 0; verbosityLevel <= 2; verbosityLevel++ {
|
||||
name := fmt.Sprintf("%s, %d message(s)", format, numMessages)
|
||||
if verbose {
|
||||
name += ", verbose"
|
||||
if verbosityLevel > 0 {
|
||||
name += fmt.Sprintf(", verbosityLevel=%d", verbosityLevel)
|
||||
}
|
||||
|
||||
_, formatter, err := RequestParserAndFormatterFor(format, source, false, !verbose, nil)
|
||||
verbose := verbosityLevel > 0
|
||||
|
||||
_, formatter, err := RequestParserAndFormatter(format, source, nil, FormatOptions{IncludeTextSeparator: !verbose})
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create parser and formatter: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
h := NewDefaultEventHandler(&buf, source, formatter, verbose)
|
||||
h := &DefaultEventHandler{
|
||||
Out: &buf,
|
||||
Formatter: formatter,
|
||||
VerbosityLevel: verbosityLevel,
|
||||
}
|
||||
|
||||
h.OnResolveMethod(md)
|
||||
h.OnSendHeaders(reqHeaders)
|
||||
|
|
@ -148,6 +154,9 @@ func TestHandler(t *testing.T) {
|
|||
expectedOutput += verbosePrefix
|
||||
}
|
||||
for i := 0; i < numMessages; i++ {
|
||||
if verbosityLevel > 1 {
|
||||
expectedOutput += verboseResponseSize
|
||||
}
|
||||
if verbose {
|
||||
expectedOutput += verboseResponseHeader
|
||||
}
|
||||
|
|
@ -226,6 +235,9 @@ Response trailers received:
|
|||
a: 1
|
||||
b: 2
|
||||
c: 3
|
||||
`
|
||||
verboseResponseSize = `
|
||||
Estimated response size: 100 bytes
|
||||
`
|
||||
verboseResponseHeader = `
|
||||
Response contents:
|
||||
|
|
|
|||
36
go.mod
36
go.mod
|
|
@ -1,12 +1,32 @@
|
|||
module github.com/fullstorydev/grpcurl
|
||||
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.24.1
|
||||
|
||||
require (
|
||||
github.com/golang/protobuf v1.3.5
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf // indirect
|
||||
github.com/goreleaser/goreleaser v0.134.0 // indirect
|
||||
github.com/jhump/protoreflect v1.6.1
|
||||
github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc // indirect
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
|
||||
google.golang.org/grpc v1.30.0
|
||||
honnef.co/go/tools v0.0.1-2020.1.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/jhump/protoreflect v1.18.0
|
||||
google.golang.org/grpc v1.66.2
|
||||
google.golang.org/protobuf v1.36.11
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.15.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.3.0 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect
|
||||
github.com/jhump/protoreflect/v2 v2.0.0-beta.1 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/oauth2 v0.27.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
|
||||
)
|
||||
|
|
|
|||
508
go.sum
508
go.sum
|
|
@ -1,456 +1,56 @@
|
|||
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.3 h1:0sMegbmn/8uTwpNkB0q9cLEpZ2W5a6kl+wtBQgPWBJQ=
|
||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
code.gitea.io/sdk/gitea v0.11.3 h1:CdI3J82Mqn0mElyEKa5DUSr3Wi2R+qm/6uVtCkSSqSM=
|
||||
code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
|
||||
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.5.0 h1:TKXjQSRS0/cCDrP7KvkgU6SmILtF/yV2TOs/02K/WZQ=
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw=
|
||||
contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
|
||||
contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA=
|
||||
github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU=
|
||||
github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo=
|
||||
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
||||
github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v30.1.0+incompatible h1:HyYPft8wXpxMd0kfLtXo6etWcO+XuPbLkcgx9g2cqxU=
|
||||
github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0=
|
||||
github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o=
|
||||
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
|
||||
github.com/Azure/go-autorest v12.0.0+incompatible h1:N+VqClcomLGD/sHb3smbSYYtNMgKpVV3Cd5r5i8z6bQ=
|
||||
github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
|
||||
github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk=
|
||||
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/apex/log v1.1.4 h1:3Zk+boorIQAAGBrHn0JUtAau4ihMamT4WdnfdnXM1zQ=
|
||||
github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ=
|
||||
github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
|
||||
github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE=
|
||||
github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||
github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.25.11 h1:wUivbsVOH3LpHdC3Rl5i+FLHfg4sOmYgv4bvHe7+/Pg=
|
||||
github.com/aws/aws-sdk-go v1.25.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||
github.com/caarlos0/ctrlc v1.0.0 h1:2DtF8GSIcajgffDFJzyG15vO+1PuBWOMUdFut7NnXhw=
|
||||
github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw=
|
||||
github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e h1:V9a67dfYqPLAvzk5hMQOXYJlZ4SLIXgyKIE+ZiHzgGQ=
|
||||
github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo=
|
||||
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e h1:hHg27A0RSSp2Om9lubZpiMgVbvn39bsUmW9U5h0twqc=
|
||||
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w=
|
||||
cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
|
||||
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
|
||||
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
|
||||
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw=
|
||||
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
|
||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
|
||||
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE=
|
||||
github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0 h1:BW6OvS3kpT5UEPbCZ+KyX/OB4Ks9/MNMhWjqPPkZxsE=
|
||||
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=
|
||||
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.3.0 h1:imGQZGEVEHpje5056+K+cgdO72p0LQv2xIIFXNGUf60=
|
||||
github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s=
|
||||
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
|
||||
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf h1:vc7Dmrk4JwS0ZPS6WZvWlwDflgDTA26jItmbSj83nug=
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||
github.com/goreleaser/goreleaser v0.134.0 h1:3ua5fSYvc/doKd5sVTzvXbyqW6H/eyuvy46woLrUFic=
|
||||
github.com/goreleaser/goreleaser v0.134.0/go.mod h1:ZT6Y2rSYa6NxQzIsdfWWNWAlYGXGbreo66NmE+3X3WQ=
|
||||
github.com/goreleaser/nfpm v1.2.1 h1:AEnu9XVmupRDTR930Z2rAs31Mj6sLIPxFcR9ESYvgDA=
|
||||
github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.2 h1:S+ef0492XaIknb8LMjcwgW2i3cNTzDYMmDrOThOJNWc=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.4 h1:BbgctKO892xEyOXnGiaAwIoSq1QZ/SS4AhjoAh9DnfY=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
|
||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
github.com/jhump/protoreflect v1.6.1 h1:4/2yi5LyDPP7nN+Hiird1SAJ6YoxUm13/oxHGRnbPd8=
|
||||
github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA=
|
||||
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
|
||||
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=
|
||||
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc h1:0NtlnvxTh8fQsQm55+bkvrqgn0zcv+M4TF8otNCuYl4=
|
||||
github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc=
|
||||
github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jhump/protoreflect v1.18.0 h1:TOz0MSR/0JOZ5kECB/0ufGnC2jdsgZ123Rd/k4Z5/2w=
|
||||
github.com/jhump/protoreflect v1.18.0/go.mod h1:ezWcltJIVF4zYdIFM+D/sHV4Oh5LNU08ORzCGfwvTz8=
|
||||
github.com/jhump/protoreflect/v2 v2.0.0-beta.1 h1:Dw1rslK/VotaUGYsv53XVWITr+5RCPXfvvlGrM/+B6w=
|
||||
github.com/jhump/protoreflect/v2 v2.0.0-beta.1/go.mod h1:D9LBEowZyv8/iSu97FU2zmXG3JxVTmNw21mu63niFzU=
|
||||
github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 h1:KPpdlQLZcHfTMQRi6bFQ7ogNO0ltFT4PmtwTLW4W+14=
|
||||
github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
|
||||
github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
|
||||
github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
|
||||
github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao=
|
||||
github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/ulikunitz/xz v0.5.7 h1:YvTNdFzX6+W5m9msiYg/zpkSURPPtOlzbqYjrFn7Yt4=
|
||||
github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/xanzy/go-gitlab v0.31.0 h1:+nHztQuCXGSMluKe5Q9IRaPdz6tO8O0gMkQ0vqGpiBk=
|
||||
github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
gocloud.dev v0.19.0 h1:EDRyaRAnMGSq/QBto486gWFxMLczAfIYUmusV7XLNBM=
|
||||
gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b h1:zSzQJAznWxAh9fZxiPy2FZo+ZZEYoYFYYDYdOrU7AaM=
|
||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0 h1:jbyannxz0XFD3zdjgrSUsaJbgpH4eTrkdhRChkHPfO8=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.29.0 h1:2pJjwYOdkZ9HlN4sWRYBg9ttH5bCOlsueaM+b/oYjwo=
|
||||
google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
||||
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
|
||||
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
|||
178
grpcurl.go
178
grpcurl.go
|
|
@ -8,31 +8,34 @@ package grpcurl
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/golang/protobuf/ptypes/struct"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import these because some of their types appear in exported API
|
||||
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/desc/protoprint"
|
||||
"github.com/jhump/protoreflect/dynamic"
|
||||
"golang.org/x/net/context"
|
||||
"github.com/jhump/protoreflect/dynamic" //lint:ignore SA1019 same as above
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
xdsCredentials "google.golang.org/grpc/credentials/xds"
|
||||
_ "google.golang.org/grpc/health" // import grpc/health to enable transparent client side checking
|
||||
"google.golang.org/grpc/metadata"
|
||||
_ "google.golang.org/grpc/xds"
|
||||
protov2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
// ListServices uses the given descriptor source to return a sorted list of fully-qualified
|
||||
|
|
@ -328,7 +331,7 @@ func fetchAllExtensions(source DescriptorSource, ext *dynamic.ExtensionRegistry,
|
|||
return nil
|
||||
}
|
||||
|
||||
// fullConvertToDynamic attempts to convert the given message to a dynamic message as well
|
||||
// fullyConvertToDynamic attempts to convert the given message to a dynamic message as well
|
||||
// as any nested messages it may contain as field values. If the given message factory has
|
||||
// extensions registered that were not known when the given message was parsed, this effectively
|
||||
// allows re-parsing to identify those extensions.
|
||||
|
|
@ -406,8 +409,9 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
|
|||
case "google.protobuf.Any":
|
||||
// empty type URL is not allowed by JSON representation
|
||||
// so we must give it a dummy type
|
||||
msg, _ := ptypes.MarshalAny(&empty.Empty{})
|
||||
return msg
|
||||
var anyVal anypb.Any
|
||||
_ = anypb.MarshalFrom(&anyVal, &emptypb.Empty{}, protov2.MarshalOptions{})
|
||||
return &anyVal
|
||||
case "google.protobuf.Value":
|
||||
// unset kind is not allowed by JSON representation
|
||||
// so we must give it something
|
||||
|
|
@ -447,11 +451,9 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
|
|||
dm := dynamic.NewMessage(md)
|
||||
|
||||
// if the message is a recursive structure, we don't want to blow the stack
|
||||
for _, seen := range path {
|
||||
if seen == md {
|
||||
// already visited this type; avoid infinite recursion
|
||||
return dm
|
||||
}
|
||||
if slices.Contains(path, md) {
|
||||
// already visited this type; avoid infinite recursion
|
||||
return dm
|
||||
}
|
||||
path = append(path, dm.GetMessageDescriptor())
|
||||
|
||||
|
|
@ -462,42 +464,42 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
|
|||
for _, fd := range dm.GetMessageDescriptor().GetFields() {
|
||||
if fd.IsRepeated() {
|
||||
switch fd.GetType() {
|
||||
case descpb.FieldDescriptorProto_TYPE_FIXED32,
|
||||
descpb.FieldDescriptorProto_TYPE_UINT32:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_FIXED32,
|
||||
descriptorpb.FieldDescriptorProto_TYPE_UINT32:
|
||||
dm.AddRepeatedField(fd, uint32(0))
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_SFIXED32,
|
||||
descpb.FieldDescriptorProto_TYPE_SINT32,
|
||||
descpb.FieldDescriptorProto_TYPE_INT32,
|
||||
descpb.FieldDescriptorProto_TYPE_ENUM:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_SFIXED32,
|
||||
descriptorpb.FieldDescriptorProto_TYPE_SINT32,
|
||||
descriptorpb.FieldDescriptorProto_TYPE_INT32,
|
||||
descriptorpb.FieldDescriptorProto_TYPE_ENUM:
|
||||
dm.AddRepeatedField(fd, int32(0))
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_FIXED64,
|
||||
descpb.FieldDescriptorProto_TYPE_UINT64:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_FIXED64,
|
||||
descriptorpb.FieldDescriptorProto_TYPE_UINT64:
|
||||
dm.AddRepeatedField(fd, uint64(0))
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_SFIXED64,
|
||||
descpb.FieldDescriptorProto_TYPE_SINT64,
|
||||
descpb.FieldDescriptorProto_TYPE_INT64:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_SFIXED64,
|
||||
descriptorpb.FieldDescriptorProto_TYPE_SINT64,
|
||||
descriptorpb.FieldDescriptorProto_TYPE_INT64:
|
||||
dm.AddRepeatedField(fd, int64(0))
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_STRING:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_STRING:
|
||||
dm.AddRepeatedField(fd, "")
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_BYTES:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
|
||||
dm.AddRepeatedField(fd, []byte{})
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_BOOL:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
|
||||
dm.AddRepeatedField(fd, false)
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_FLOAT:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
|
||||
dm.AddRepeatedField(fd, float32(0))
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_DOUBLE:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
|
||||
dm.AddRepeatedField(fd, float64(0))
|
||||
|
||||
case descpb.FieldDescriptorProto_TYPE_MESSAGE,
|
||||
descpb.FieldDescriptorProto_TYPE_GROUP:
|
||||
case descriptorpb.FieldDescriptorProto_TYPE_MESSAGE,
|
||||
descriptorpb.FieldDescriptorProto_TYPE_GROUP:
|
||||
dm.AddRepeatedField(fd, makeTemplate(fd.GetMessageType(), path))
|
||||
}
|
||||
} else if fd.GetMessageType() != nil {
|
||||
|
|
@ -507,11 +509,25 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
|
|||
return dm
|
||||
}
|
||||
|
||||
// ClientTransportCredentials builds transport credentials for a gRPC client using the
|
||||
// ClientTransportCredentials is a helper function that constructs a TLS config with
|
||||
// the given properties (see ClientTLSConfig) and then constructs and returns gRPC
|
||||
// transport credentials using that config.
|
||||
//
|
||||
// Deprecated: Use grpcurl.ClientTLSConfig and credentials.NewTLS instead.
|
||||
func ClientTransportCredentials(insecureSkipVerify bool, cacertFile, clientCertFile, clientKeyFile string) (credentials.TransportCredentials, error) {
|
||||
tlsConf, err := ClientTLSConfig(insecureSkipVerify, cacertFile, clientCertFile, clientKeyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return credentials.NewTLS(tlsConf), nil
|
||||
}
|
||||
|
||||
// ClientTLSConfig builds transport-layer config for a gRPC client using the
|
||||
// given properties. If cacertFile is blank, only standard trusted certs are used to
|
||||
// verify the server certs. If clientCertFile is blank, the client will not use a client
|
||||
// certificate. If clientCertFile is not blank then clientKeyFile must not be blank.
|
||||
func ClientTransportCredentials(insecureSkipVerify bool, cacertFile, clientCertFile, clientKeyFile string) (credentials.TransportCredentials, error) {
|
||||
func ClientTLSConfig(insecureSkipVerify bool, cacertFile, clientCertFile, clientKeyFile string) (*tls.Config, error) {
|
||||
var tlsConf tls.Config
|
||||
|
||||
if clientCertFile != "" {
|
||||
|
|
@ -528,7 +544,7 @@ func ClientTransportCredentials(insecureSkipVerify bool, cacertFile, clientCertF
|
|||
} else if cacertFile != "" {
|
||||
// Create a certificate pool from the certificate authority
|
||||
certPool := x509.NewCertPool()
|
||||
ca, err := ioutil.ReadFile(cacertFile)
|
||||
ca, err := os.ReadFile(cacertFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read ca certificate: %v", err)
|
||||
}
|
||||
|
|
@ -541,7 +557,7 @@ func ClientTransportCredentials(insecureSkipVerify bool, cacertFile, clientCertF
|
|||
tlsConf.RootCAs = certPool
|
||||
}
|
||||
|
||||
return credentials.NewTLS(&tlsConf), nil
|
||||
return &tlsConf, nil
|
||||
}
|
||||
|
||||
// ServerTransportCredentials builds transport credentials for a gRPC server using the
|
||||
|
|
@ -565,7 +581,7 @@ func ServerTransportCredentials(cacertFile, serverCertFile, serverKeyFile string
|
|||
if cacertFile != "" {
|
||||
// Create a certificate pool from the certificate authority
|
||||
certPool := x509.NewCertPool()
|
||||
ca, err := ioutil.ReadFile(cacertFile)
|
||||
ca, err := os.ReadFile(cacertFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read ca certificate: %v", err)
|
||||
}
|
||||
|
|
@ -592,7 +608,24 @@ func ServerTransportCredentials(cacertFile, serverCertFile, serverKeyFile string
|
|||
// BlockingDial is a helper method to dial the given address, using optional TLS credentials,
|
||||
// and blocking until the returned connection is ready. If the given credentials are nil, the
|
||||
// connection will be insecure (plain-text).
|
||||
// The network parameter should be left empty in most cases when your address is a RFC 3986
|
||||
// compliant URI. The resolver from grpc-go will resolve the correct network type.
|
||||
func BlockingDial(ctx context.Context, network, address string, creds credentials.TransportCredentials, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
|
||||
if creds == nil {
|
||||
creds = insecure.NewCredentials()
|
||||
}
|
||||
|
||||
var err error
|
||||
if strings.HasPrefix(address, "xds:///") {
|
||||
// The xds:/// prefix is used to signal to the gRPC client to use an xDS server to resolve the
|
||||
// target. The relevant credentials will be automatically pulled from the GRPC_XDS_BOOTSTRAP or
|
||||
// GRPC_XDS_BOOTSTRAP_CONFIG env vars.
|
||||
creds, err = xdsCredentials.NewClientCredentials(xdsCredentials.ClientOptions{FallbackCreds: creds})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// grpc.Dial doesn't provide any information on permanent connection errors (like
|
||||
// TLS handshake failures). So in order to provide good error messages, we need a
|
||||
// custom dialer that can provide that info. That means we manage the TLS handshake.
|
||||
|
|
@ -608,25 +641,37 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
|
|||
|
||||
// custom credentials and dialer will notify on error via the
|
||||
// writeResult function
|
||||
if creds != nil {
|
||||
creds = &errSignalingCreds{
|
||||
TransportCredentials: creds,
|
||||
writeResult: writeResult,
|
||||
}
|
||||
creds = &errSignalingCreds{
|
||||
TransportCredentials: creds,
|
||||
writeResult: writeResult,
|
||||
}
|
||||
dialer := func(ctx context.Context, address string) (net.Conn, error) {
|
||||
// NB: We *could* handle the TLS handshake ourselves, in the custom
|
||||
// dialer (instead of customizing both the dialer and the credentials).
|
||||
// But that requires using WithInsecure dial option (so that the gRPC
|
||||
// library doesn't *also* try to do a handshake). And that would mean
|
||||
// that the library would send the wrong ":scheme" metaheader to
|
||||
// servers: it would send "http" instead of "https" because it is
|
||||
// unaware that TLS is actually in use.
|
||||
conn, err := (&net.Dialer{}).DialContext(ctx, network, address)
|
||||
if err != nil {
|
||||
writeResult(err)
|
||||
|
||||
switch network {
|
||||
case "":
|
||||
// no-op, use address as-is
|
||||
case "tcp":
|
||||
if strings.HasPrefix(address, "unix://") {
|
||||
return nil, fmt.Errorf("tcp network type cannot use unix address %s", address)
|
||||
}
|
||||
return conn, err
|
||||
case "unix":
|
||||
if !strings.HasPrefix(address, "unix://") {
|
||||
// prepend unix:// to the address if it's not already there
|
||||
// this is to maintain backwards compatibility because the custom dialer is replaced by
|
||||
// the default dialer in grpc-go.
|
||||
// https://github.com/fullstorydev/grpcurl/pull/480
|
||||
address = "unix://" + address
|
||||
}
|
||||
default:
|
||||
// custom dialer for other networks
|
||||
dialer := func(ctx context.Context, address string) (net.Conn, error) {
|
||||
conn, err := (&net.Dialer{}).DialContext(ctx, network, address)
|
||||
if err != nil {
|
||||
// capture the error so we can provide a better message
|
||||
writeResult(err)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
opts = append([]grpc.DialOption{grpc.WithContextDialer(dialer)}, opts...)
|
||||
}
|
||||
|
||||
// Even with grpc.FailOnNonTempDialError, this call will usually timeout in
|
||||
|
|
@ -634,16 +679,13 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
|
|||
// know when we're done. So we run it in a goroutine and then use result
|
||||
// channel to either get the connection or fail-fast.
|
||||
go func() {
|
||||
opts = append(opts,
|
||||
grpc.WithBlock(),
|
||||
grpc.FailOnNonTempDialError(true),
|
||||
grpc.WithContextDialer(dialer),
|
||||
)
|
||||
if creds == nil {
|
||||
opts = append(opts, grpc.WithInsecure())
|
||||
} else {
|
||||
opts = append(opts, grpc.WithTransportCredentials(creds))
|
||||
}
|
||||
// We put grpc.FailOnNonTempDialError *before* the explicitly provided
|
||||
// options so that it could be overridden.
|
||||
opts = append([]grpc.DialOption{grpc.FailOnNonTempDialError(true)}, opts...)
|
||||
// But we don't want caller to be able to override these two, so we put
|
||||
// them *after* the explicitly provided options.
|
||||
opts = append(opts, grpc.WithBlock(), grpc.WithTransportCredentials(creds))
|
||||
|
||||
conn, err := grpc.DialContext(ctx, address, opts...)
|
||||
var res interface{}
|
||||
if err != nil {
|
||||
|
|
|
|||
179
grpcurl_test.go
179
grpcurl_test.go
|
|
@ -1,6 +1,7 @@
|
|||
package grpcurl_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -11,22 +12,20 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 we have to import these because some of their types appear in exported API
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/grpcreflect"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/interop/grpc_testing"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/reflection"
|
||||
reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
. "github.com/fullstorydev/grpcurl"
|
||||
grpcurl_testing "github.com/fullstorydev/grpcurl/testing"
|
||||
jsonpbtest "github.com/fullstorydev/grpcurl/testing/jsonpb_test_proto"
|
||||
grpcurl_testing "github.com/fullstorydev/grpcurl/internal/testing"
|
||||
jsonpbtest "github.com/fullstorydev/grpcurl/internal/testing/jsonpb_test_proto"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -52,18 +51,18 @@ type descSourceCase struct {
|
|||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
sourceProtoset, err = DescriptorSourceFromProtoSets("testing/test.protoset")
|
||||
sourceProtoset, err = DescriptorSourceFromProtoSets("internal/testing/test.protoset")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sourceProtoFiles, err = DescriptorSourceFromProtoFiles(nil, "testing/test.proto")
|
||||
sourceProtoFiles, err = DescriptorSourceFromProtoFiles([]string{"internal/testing"}, "test.proto")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create a server that includes the reflection service
|
||||
svrReflect := grpc.NewServer()
|
||||
grpc_testing.RegisterTestServiceServer(svrReflect, grpcurl_testing.TestServer{})
|
||||
grpcurl_testing.RegisterTestServiceServer(svrReflect, grpcurl_testing.TestServer{})
|
||||
reflection.Register(svrReflect)
|
||||
var portReflect int
|
||||
if l, err := net.Listen("tcp", "127.0.0.1:0"); err != nil {
|
||||
|
|
@ -78,18 +77,18 @@ func TestMain(m *testing.M) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
if ccReflect, err = grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%d", portReflect),
|
||||
grpc.WithInsecure(), grpc.WithBlock()); err != nil {
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer ccReflect.Close()
|
||||
refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(ccReflect))
|
||||
refClient := grpcreflect.NewClientAuto(context.Background(), ccReflect)
|
||||
defer refClient.Reset()
|
||||
|
||||
sourceReflect = DescriptorSourceFromServer(context.Background(), refClient)
|
||||
|
||||
// Also create a server that does *not* include the reflection service
|
||||
svrProtoset := grpc.NewServer()
|
||||
grpc_testing.RegisterTestServiceServer(svrProtoset, grpcurl_testing.TestServer{})
|
||||
grpcurl_testing.RegisterTestServiceServer(svrProtoset, grpcurl_testing.TestServer{})
|
||||
var portProtoset int
|
||||
if l, err := net.Listen("tcp", "127.0.0.1:0"); err != nil {
|
||||
panic(err)
|
||||
|
|
@ -103,7 +102,7 @@ func TestMain(m *testing.M) {
|
|||
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
if ccNoReflect, err = grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%d", portProtoset),
|
||||
grpc.WithInsecure(), grpc.WithBlock()); err != nil {
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer ccNoReflect.Close()
|
||||
|
|
@ -118,7 +117,7 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
|
||||
func TestServerDoesNotSupportReflection(t *testing.T) {
|
||||
refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(ccNoReflect))
|
||||
refClient := grpcreflect.NewClientAuto(context.Background(), ccNoReflect)
|
||||
defer refClient.Reset()
|
||||
|
||||
refSource := DescriptorSourceFromServer(context.Background(), refClient)
|
||||
|
|
@ -141,7 +140,7 @@ func TestServerDoesNotSupportReflection(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestProtosetWithImports(t *testing.T) {
|
||||
sourceProtoset, err := DescriptorSourceFromProtoSets("testing/example.protoset")
|
||||
sourceProtoset, err := DescriptorSourceFromProtoSets("internal/testing/example.protoset")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load protoset: %v", err)
|
||||
}
|
||||
|
|
@ -178,11 +177,11 @@ func doTestListServices(t *testing.T, source DescriptorSource, includeReflection
|
|||
var expected []string
|
||||
if includeReflection {
|
||||
// when using server reflection, we see the TestService as well as the ServerReflection service
|
||||
expected = []string{"grpc.reflection.v1alpha.ServerReflection", "grpc.testing.TestService"}
|
||||
expected = []string{"grpc.reflection.v1.ServerReflection", "grpc.reflection.v1alpha.ServerReflection", "testing.TestService"}
|
||||
} else {
|
||||
// without reflection, we see all services defined in the same test.proto file, which is the
|
||||
// TestService as well as UnimplementedService
|
||||
expected = []string{"grpc.testing.TestService", "grpc.testing.UnimplementedService"}
|
||||
expected = []string{"testing.TestService", "testing.UnimplementedService"}
|
||||
}
|
||||
if !reflect.DeepEqual(expected, names) {
|
||||
t.Errorf("ListServices returned wrong results: wanted %v, got %v", expected, names)
|
||||
|
|
@ -198,17 +197,17 @@ func TestListMethods(t *testing.T) {
|
|||
}
|
||||
|
||||
func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection bool) {
|
||||
names, err := ListMethods(source, "grpc.testing.TestService")
|
||||
names, err := ListMethods(source, "testing.TestService")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list methods for TestService: %v", err)
|
||||
}
|
||||
expected := []string{
|
||||
"grpc.testing.TestService.EmptyCall",
|
||||
"grpc.testing.TestService.FullDuplexCall",
|
||||
"grpc.testing.TestService.HalfDuplexCall",
|
||||
"grpc.testing.TestService.StreamingInputCall",
|
||||
"grpc.testing.TestService.StreamingOutputCall",
|
||||
"grpc.testing.TestService.UnaryCall",
|
||||
"testing.TestService.EmptyCall",
|
||||
"testing.TestService.FullDuplexCall",
|
||||
"testing.TestService.HalfDuplexCall",
|
||||
"testing.TestService.StreamingInputCall",
|
||||
"testing.TestService.StreamingOutputCall",
|
||||
"testing.TestService.UnaryCall",
|
||||
}
|
||||
if !reflect.DeepEqual(expected, names) {
|
||||
t.Errorf("ListMethods returned wrong results: wanted %v, got %v", expected, names)
|
||||
|
|
@ -216,19 +215,19 @@ func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection
|
|||
|
||||
if includeReflection {
|
||||
// when using server reflection, we see the TestService as well as the ServerReflection service
|
||||
names, err = ListMethods(source, "grpc.reflection.v1alpha.ServerReflection")
|
||||
names, err = ListMethods(source, "grpc.reflection.v1.ServerReflection")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list methods for ServerReflection: %v", err)
|
||||
}
|
||||
expected = []string{"grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo"}
|
||||
expected = []string{"grpc.reflection.v1.ServerReflection.ServerReflectionInfo"}
|
||||
} else {
|
||||
// without reflection, we see all services defined in the same test.proto file, which is the
|
||||
// TestService as well as UnimplementedService
|
||||
names, err = ListMethods(source, "grpc.testing.UnimplementedService")
|
||||
names, err = ListMethods(source, "testing.UnimplementedService")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list methods for ServerReflection: %v", err)
|
||||
}
|
||||
expected = []string{"grpc.testing.UnimplementedService.UnimplementedCall"}
|
||||
expected = []string{"testing.UnimplementedService.UnimplementedCall"}
|
||||
}
|
||||
if !reflect.DeepEqual(expected, names) {
|
||||
t.Errorf("ListMethods returned wrong results: wanted %v, got %v", expected, names)
|
||||
|
|
@ -242,13 +241,9 @@ func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection
|
|||
}
|
||||
|
||||
func TestGetAllFiles(t *testing.T) {
|
||||
expectedFiles := []string{"testing/test.proto"}
|
||||
// server reflection picks up filename from linked in Go package,
|
||||
// which indicates "grpc_testing/test.proto", not our local copy.
|
||||
expectedFilesWithReflection := [][]string{
|
||||
{"grpc_reflection_v1alpha/reflection.proto", "grpc_testing/test.proto"},
|
||||
// depending on the version of grpc, the filenames could be prefixed with "interop/" and "reflection/"
|
||||
{"interop/grpc_testing/test.proto", "reflection/grpc_reflection_v1alpha/reflection.proto"},
|
||||
expectedFiles := []string{"test.proto"}
|
||||
expectedFilesWithReflection := []string{
|
||||
"grpc/reflection/v1/reflection.proto", "grpc/reflection/v1alpha/reflection.proto", "test.proto",
|
||||
}
|
||||
|
||||
for _, ds := range descSources {
|
||||
|
|
@ -261,17 +256,11 @@ func TestGetAllFiles(t *testing.T) {
|
|||
match := false
|
||||
var expected []string
|
||||
if ds.includeRefl {
|
||||
for _, expectedNames := range expectedFilesWithReflection {
|
||||
expected = expectedNames
|
||||
if reflect.DeepEqual(expected, names) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
expected = expectedFilesWithReflection
|
||||
} else {
|
||||
expected = expectedFiles
|
||||
match = reflect.DeepEqual(expected, names)
|
||||
}
|
||||
match = reflect.DeepEqual(expected, names)
|
||||
if !match {
|
||||
t.Errorf("GetAllFiles returned wrong results: wanted %v, got %v", expected, names)
|
||||
}
|
||||
|
|
@ -279,11 +268,11 @@ func TestGetAllFiles(t *testing.T) {
|
|||
}
|
||||
|
||||
// try cases with more complicated set of files
|
||||
otherSourceProtoset, err := DescriptorSourceFromProtoSets("testing/test.protoset", "testing/example.protoset")
|
||||
otherSourceProtoset, err := DescriptorSourceFromProtoSets("internal/testing/test.protoset", "internal/testing/example.protoset")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
otherSourceProtoFiles, err := DescriptorSourceFromProtoFiles(nil, "testing/test.proto", "testing/example.proto")
|
||||
otherSourceProtoFiles, err := DescriptorSourceFromProtoFiles([]string{"internal/testing"}, "test.proto", "example.proto")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
|
@ -292,13 +281,13 @@ func TestGetAllFiles(t *testing.T) {
|
|||
{"proto[b]", otherSourceProtoFiles, false},
|
||||
}
|
||||
expectedFiles = []string{
|
||||
"example.proto",
|
||||
"example2.proto",
|
||||
"google/protobuf/any.proto",
|
||||
"google/protobuf/descriptor.proto",
|
||||
"google/protobuf/empty.proto",
|
||||
"google/protobuf/timestamp.proto",
|
||||
"testing/example.proto",
|
||||
"testing/example2.proto",
|
||||
"testing/test.proto",
|
||||
"test.proto",
|
||||
}
|
||||
for _, ds := range otherDescSources {
|
||||
t.Run(ds.name, func(t *testing.T) {
|
||||
|
|
@ -403,7 +392,7 @@ func TestDescribe(t *testing.T) {
|
|||
}
|
||||
|
||||
func doTestDescribe(t *testing.T, source DescriptorSource) {
|
||||
sym := "grpc.testing.TestService.EmptyCall"
|
||||
sym := "testing.TestService.EmptyCall"
|
||||
dsc, err := source.FindSymbol(sym)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get descriptor for %q: %v", sym, err)
|
||||
|
|
@ -414,14 +403,14 @@ func doTestDescribe(t *testing.T, source DescriptorSource) {
|
|||
txt := proto.MarshalTextString(dsc.AsProto())
|
||||
expected :=
|
||||
`name: "EmptyCall"
|
||||
input_type: ".grpc.testing.Empty"
|
||||
output_type: ".grpc.testing.Empty"
|
||||
input_type: ".testing.Empty"
|
||||
output_type: ".testing.Empty"
|
||||
`
|
||||
if expected != txt {
|
||||
t.Errorf("descriptor mismatch: expected %s, got %s", expected, txt)
|
||||
}
|
||||
|
||||
sym = "grpc.testing.StreamingOutputCallResponse"
|
||||
sym = "testing.StreamingOutputCallResponse"
|
||||
dsc, err = source.FindSymbol(sym)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get descriptor for %q: %v", sym, err)
|
||||
|
|
@ -437,7 +426,7 @@ field: <
|
|||
number: 1
|
||||
label: LABEL_OPTIONAL
|
||||
type: TYPE_MESSAGE
|
||||
type_name: ".grpc.testing.Payload"
|
||||
type_name: ".testing.Payload"
|
||||
json_name: "payload"
|
||||
>
|
||||
`
|
||||
|
|
@ -493,12 +482,12 @@ func TestUnary(t *testing.T) {
|
|||
func doTestUnary(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
|
||||
// Success
|
||||
h := &handler{reqMessages: []string{payload1}}
|
||||
err := InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/UnaryCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
err := InvokeRpc(context.Background(), source, cc, "testing.TestService/UnaryCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
if h.check(t, "grpc.testing.TestService.UnaryCall", codes.OK, 1, 1) {
|
||||
if h.check(t, "testing.TestService.UnaryCall", codes.OK, 1, 1) {
|
||||
if h.respMessages[0] != payload1 {
|
||||
t.Errorf("unexpected response from RPC: expecting %s; got %s", payload1, h.respMessages[0])
|
||||
}
|
||||
|
|
@ -506,12 +495,12 @@ func doTestUnary(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
|
|||
|
||||
// Failure
|
||||
h = &handler{reqMessages: []string{payload1}}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/UnaryCall", makeHeaders(codes.NotFound), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/UnaryCall", makeHeaders(codes.NotFound), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.UnaryCall", codes.NotFound, 1, 0)
|
||||
h.check(t, "testing.TestService.UnaryCall", codes.NotFound, 1, 0)
|
||||
}
|
||||
|
||||
func TestClientStream(t *testing.T) {
|
||||
|
|
@ -525,12 +514,12 @@ func TestClientStream(t *testing.T) {
|
|||
func doTestClientStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
|
||||
// Success
|
||||
h := &handler{reqMessages: []string{payload1, payload2, payload3}}
|
||||
err := InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingInputCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
err := InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingInputCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
if h.check(t, "grpc.testing.TestService.StreamingInputCall", codes.OK, 3, 1) {
|
||||
if h.check(t, "testing.TestService.StreamingInputCall", codes.OK, 3, 1) {
|
||||
expected :=
|
||||
`{
|
||||
"aggregatedPayloadSize": 61
|
||||
|
|
@ -542,21 +531,21 @@ func doTestClientStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSour
|
|||
|
||||
// Fail fast (server rejects as soon as possible)
|
||||
h = &handler{reqMessages: []string{payload1, payload2, payload3}}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingInputCall", makeHeaders(codes.InvalidArgument), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingInputCall", makeHeaders(codes.InvalidArgument), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.StreamingInputCall", codes.InvalidArgument, -3, 0)
|
||||
h.check(t, "testing.TestService.StreamingInputCall", codes.InvalidArgument, -3, 0)
|
||||
|
||||
// Fail late (server waits until stream is complete to reject)
|
||||
h = &handler{reqMessages: []string{payload1, payload2, payload3}}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingInputCall", makeHeaders(codes.Internal, true), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingInputCall", makeHeaders(codes.Internal, true), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.StreamingInputCall", codes.Internal, 3, 0)
|
||||
h.check(t, "testing.TestService.StreamingInputCall", codes.Internal, 3, 0)
|
||||
}
|
||||
|
||||
func TestServerStream(t *testing.T) {
|
||||
|
|
@ -568,9 +557,9 @@ func TestServerStream(t *testing.T) {
|
|||
}
|
||||
|
||||
func doTestServerStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
|
||||
req := &grpc_testing.StreamingOutputCallRequest{
|
||||
ResponseType: grpc_testing.PayloadType_COMPRESSABLE,
|
||||
ResponseParameters: []*grpc_testing.ResponseParameters{
|
||||
req := &grpcurl_testing.StreamingOutputCallRequest{
|
||||
ResponseType: grpcurl_testing.PayloadType_COMPRESSABLE,
|
||||
ResponseParameters: []*grpcurl_testing.ResponseParameters{
|
||||
{Size: 10}, {Size: 20}, {Size: 30}, {Size: 40}, {Size: 50},
|
||||
},
|
||||
}
|
||||
|
|
@ -581,19 +570,19 @@ func doTestServerStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSour
|
|||
|
||||
// Success
|
||||
h := &handler{reqMessages: []string{payload}}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingOutputCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingOutputCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
if h.check(t, "grpc.testing.TestService.StreamingOutputCall", codes.OK, 1, 5) {
|
||||
resp := &grpc_testing.StreamingOutputCallResponse{}
|
||||
if h.check(t, "testing.TestService.StreamingOutputCall", codes.OK, 1, 5) {
|
||||
resp := &grpcurl_testing.StreamingOutputCallResponse{}
|
||||
for i, msg := range h.respMessages {
|
||||
if err := jsonpb.UnmarshalString(msg, resp); err != nil {
|
||||
t.Errorf("failed to parse response %d: %v", i+1, err)
|
||||
}
|
||||
if resp.Payload.GetType() != grpc_testing.PayloadType_COMPRESSABLE {
|
||||
t.Errorf("response %d has wrong payload type; expecting %v, got %v", i, grpc_testing.PayloadType_COMPRESSABLE, resp.Payload.Type)
|
||||
if resp.Payload.GetType() != grpcurl_testing.PayloadType_COMPRESSABLE {
|
||||
t.Errorf("response %d has wrong payload type; expecting %v, got %v", i, grpcurl_testing.PayloadType_COMPRESSABLE, resp.Payload.Type)
|
||||
}
|
||||
if len(resp.Payload.Body) != (i+1)*10 {
|
||||
t.Errorf("response %d has wrong payload size; expecting %d, got %d", i, (i+1)*10, len(resp.Payload.Body))
|
||||
|
|
@ -604,21 +593,21 @@ func doTestServerStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSour
|
|||
|
||||
// Fail fast (server rejects as soon as possible)
|
||||
h = &handler{reqMessages: []string{payload}}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingOutputCall", makeHeaders(codes.Aborted), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingOutputCall", makeHeaders(codes.Aborted), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.StreamingOutputCall", codes.Aborted, 1, 0)
|
||||
h.check(t, "testing.TestService.StreamingOutputCall", codes.Aborted, 1, 0)
|
||||
|
||||
// Fail late (server waits until stream is complete to reject)
|
||||
h = &handler{reqMessages: []string{payload}}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingOutputCall", makeHeaders(codes.AlreadyExists, true), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingOutputCall", makeHeaders(codes.AlreadyExists, true), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.StreamingOutputCall", codes.AlreadyExists, 1, 5)
|
||||
h.check(t, "testing.TestService.StreamingOutputCall", codes.AlreadyExists, 1, 5)
|
||||
}
|
||||
|
||||
func TestHalfDuplexStream(t *testing.T) {
|
||||
|
|
@ -634,12 +623,12 @@ func doTestHalfDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
|
|||
|
||||
// Success
|
||||
h := &handler{reqMessages: reqs}
|
||||
err := InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/HalfDuplexCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
err := InvokeRpc(context.Background(), source, cc, "testing.TestService/HalfDuplexCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
if h.check(t, "grpc.testing.TestService.HalfDuplexCall", codes.OK, 3, 3) {
|
||||
if h.check(t, "testing.TestService.HalfDuplexCall", codes.OK, 3, 3) {
|
||||
for i, resp := range h.respMessages {
|
||||
if resp != reqs[i] {
|
||||
t.Errorf("unexpected response %d from RPC:\nexpecting %q\ngot %q", i, reqs[i], resp)
|
||||
|
|
@ -649,21 +638,21 @@ func doTestHalfDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
|
|||
|
||||
// Fail fast (server rejects as soon as possible)
|
||||
h = &handler{reqMessages: reqs}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/HalfDuplexCall", makeHeaders(codes.Canceled), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/HalfDuplexCall", makeHeaders(codes.Canceled), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.HalfDuplexCall", codes.Canceled, -3, 0)
|
||||
h.check(t, "testing.TestService.HalfDuplexCall", codes.Canceled, -3, 0)
|
||||
|
||||
// Fail late (server waits until stream is complete to reject)
|
||||
h = &handler{reqMessages: reqs}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/HalfDuplexCall", makeHeaders(codes.DataLoss, true), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/HalfDuplexCall", makeHeaders(codes.DataLoss, true), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.HalfDuplexCall", codes.DataLoss, 3, 3)
|
||||
h.check(t, "testing.TestService.HalfDuplexCall", codes.DataLoss, 3, 3)
|
||||
}
|
||||
|
||||
func TestFullDuplexStream(t *testing.T) {
|
||||
|
|
@ -676,11 +665,11 @@ func TestFullDuplexStream(t *testing.T) {
|
|||
|
||||
func doTestFullDuplexStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
|
||||
reqs := make([]string, 3)
|
||||
req := &grpc_testing.StreamingOutputCallRequest{
|
||||
ResponseType: grpc_testing.PayloadType_RANDOM,
|
||||
req := &grpcurl_testing.StreamingOutputCallRequest{
|
||||
ResponseType: grpcurl_testing.PayloadType_RANDOM,
|
||||
}
|
||||
for i := range reqs {
|
||||
req.ResponseParameters = append(req.ResponseParameters, &grpc_testing.ResponseParameters{Size: int32((i + 1) * 10)})
|
||||
req.ResponseParameters = append(req.ResponseParameters, &grpcurl_testing.ResponseParameters{Size: int32((i + 1) * 10)})
|
||||
payload, err := (&jsonpb.Marshaler{}).MarshalToString(req)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to construct request %d: %v", i, err)
|
||||
|
|
@ -690,13 +679,13 @@ func doTestFullDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
|
|||
|
||||
// Success
|
||||
h := &handler{reqMessages: reqs}
|
||||
err := InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/FullDuplexCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
err := InvokeRpc(context.Background(), source, cc, "testing.TestService/FullDuplexCall", makeHeaders(codes.OK), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
if h.check(t, "grpc.testing.TestService.FullDuplexCall", codes.OK, 3, 6) {
|
||||
resp := &grpc_testing.StreamingOutputCallResponse{}
|
||||
if h.check(t, "testing.TestService.FullDuplexCall", codes.OK, 3, 6) {
|
||||
resp := &grpcurl_testing.StreamingOutputCallResponse{}
|
||||
i := 0
|
||||
for j := 1; j < 3; j++ {
|
||||
// three requests
|
||||
|
|
@ -706,8 +695,8 @@ func doTestFullDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
|
|||
if err := jsonpb.UnmarshalString(msg, resp); err != nil {
|
||||
t.Errorf("failed to parse response %d: %v", i+1, err)
|
||||
}
|
||||
if resp.Payload.GetType() != grpc_testing.PayloadType_RANDOM {
|
||||
t.Errorf("response %d has wrong payload type; expecting %v, got %v", i, grpc_testing.PayloadType_RANDOM, resp.Payload.Type)
|
||||
if resp.Payload.GetType() != grpcurl_testing.PayloadType_RANDOM {
|
||||
t.Errorf("response %d has wrong payload type; expecting %v, got %v", i, grpcurl_testing.PayloadType_RANDOM, resp.Payload.Type)
|
||||
}
|
||||
if len(resp.Payload.Body) != (k+1)*10 {
|
||||
t.Errorf("response %d has wrong payload size; expecting %d, got %d", i, (k+1)*10, len(resp.Payload.Body))
|
||||
|
|
@ -721,21 +710,21 @@ func doTestFullDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
|
|||
|
||||
// Fail fast (server rejects as soon as possible)
|
||||
h = &handler{reqMessages: reqs}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/FullDuplexCall", makeHeaders(codes.PermissionDenied), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/FullDuplexCall", makeHeaders(codes.PermissionDenied), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.FullDuplexCall", codes.PermissionDenied, -3, 0)
|
||||
h.check(t, "testing.TestService.FullDuplexCall", codes.PermissionDenied, -3, 0)
|
||||
|
||||
// Fail late (server waits until stream is complete to reject)
|
||||
h = &handler{reqMessages: reqs}
|
||||
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/FullDuplexCall", makeHeaders(codes.ResourceExhausted, true), h, h.getRequestData)
|
||||
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/FullDuplexCall", makeHeaders(codes.ResourceExhausted, true), h, h.getRequestData)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error during RPC: %v", err)
|
||||
}
|
||||
|
||||
h.check(t, "grpc.testing.TestService.FullDuplexCall", codes.ResourceExhausted, 3, 6)
|
||||
h.check(t, "testing.TestService.FullDuplexCall", codes.ResourceExhausted, 3, 6)
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// bankServer implements the Bank gRPC service.
|
||||
type bankServer struct {
|
||||
UnimplementedBankServer
|
||||
allAccounts *accounts
|
||||
}
|
||||
|
||||
|
|
@ -72,26 +72,29 @@ func (s *bankServer) GetTransactions(req *GetTransactionsRequest, stream Bank_Ge
|
|||
|
||||
var start, end time.Time
|
||||
if req.Start != nil {
|
||||
start, err = ptypes.Timestamp(req.Start)
|
||||
err := req.Start.CheckValid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
start = req.Start.AsTime()
|
||||
}
|
||||
if req.End != nil {
|
||||
end, err = ptypes.Timestamp(req.End)
|
||||
err := req.End.CheckValid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
end = req.End.AsTime()
|
||||
} else {
|
||||
end = time.Date(9999, 12, 31, 23, 59, 59, 999999999, time.Local)
|
||||
}
|
||||
|
||||
txns := acct.getTransactions()
|
||||
for _, txn := range txns {
|
||||
t, err := ptypes.Timestamp(txn.Date)
|
||||
err := txn.Date.CheckValid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t := txn.Date.AsTime()
|
||||
if (t.After(start) || t.Equal(start)) &&
|
||||
(t.Before(end) || t.Equal(end)) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,6 @@
|
|||
syntax = "proto3";
|
||||
|
||||
option go_package = "main";
|
||||
option go_package = ".;main";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
|
@ -0,0 +1,374 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// BankClient is the client API for Bank service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type BankClient interface {
|
||||
// OpenAccount creates an account with the type and given initial deposit
|
||||
// as its balance.
|
||||
OpenAccount(ctx context.Context, in *OpenAccountRequest, opts ...grpc.CallOption) (*Account, error)
|
||||
// CloseAccount closes the indicated account. An account can only be
|
||||
// closed if its balance is zero.
|
||||
CloseAccount(ctx context.Context, in *CloseAccountRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// GetAccounts lists all accounts for the current customer.
|
||||
GetAccounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetAccountsResponse, error)
|
||||
// GetTransactions streams all transactions that match the given criteria.
|
||||
// If the given start date is not specified, transactions since beginning
|
||||
// of time are included. Similarly, if the given end date is not specified,
|
||||
// transactions all the way to the presnet are included.
|
||||
GetTransactions(ctx context.Context, in *GetTransactionsRequest, opts ...grpc.CallOption) (Bank_GetTransactionsClient, error)
|
||||
// Deposit increases the balance of an account by depositing funds into it.
|
||||
Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*BalanceResponse, error)
|
||||
// Withdraw decreases the balance of an account by withdrawing funds from it.
|
||||
Withdraw(ctx context.Context, in *WithdrawRequest, opts ...grpc.CallOption) (*BalanceResponse, error)
|
||||
// Transfer moves money from one account to another. The source and destination
|
||||
// accounts can be with this bank (e.g. "local" account numbers) or can be
|
||||
// external accounts, identified by their ACH routing and account numbers.
|
||||
Transfer(ctx context.Context, in *TransferRequest, opts ...grpc.CallOption) (*TransferResponse, error)
|
||||
}
|
||||
|
||||
type bankClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewBankClient(cc grpc.ClientConnInterface) BankClient {
|
||||
return &bankClient{cc}
|
||||
}
|
||||
|
||||
func (c *bankClient) OpenAccount(ctx context.Context, in *OpenAccountRequest, opts ...grpc.CallOption) (*Account, error) {
|
||||
out := new(Account)
|
||||
err := c.cc.Invoke(ctx, "/Bank/OpenAccount", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) CloseAccount(ctx context.Context, in *CloseAccountRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/Bank/CloseAccount", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) GetAccounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetAccountsResponse, error) {
|
||||
out := new(GetAccountsResponse)
|
||||
err := c.cc.Invoke(ctx, "/Bank/GetAccounts", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) GetTransactions(ctx context.Context, in *GetTransactionsRequest, opts ...grpc.CallOption) (Bank_GetTransactionsClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Bank_ServiceDesc.Streams[0], "/Bank/GetTransactions", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &bankGetTransactionsClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Bank_GetTransactionsClient interface {
|
||||
Recv() (*Transaction, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type bankGetTransactionsClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *bankGetTransactionsClient) Recv() (*Transaction, error) {
|
||||
m := new(Transaction)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*BalanceResponse, error) {
|
||||
out := new(BalanceResponse)
|
||||
err := c.cc.Invoke(ctx, "/Bank/Deposit", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) Withdraw(ctx context.Context, in *WithdrawRequest, opts ...grpc.CallOption) (*BalanceResponse, error) {
|
||||
out := new(BalanceResponse)
|
||||
err := c.cc.Invoke(ctx, "/Bank/Withdraw", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) Transfer(ctx context.Context, in *TransferRequest, opts ...grpc.CallOption) (*TransferResponse, error) {
|
||||
out := new(TransferResponse)
|
||||
err := c.cc.Invoke(ctx, "/Bank/Transfer", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// BankServer is the server API for Bank service.
|
||||
// All implementations must embed UnimplementedBankServer
|
||||
// for forward compatibility
|
||||
type BankServer interface {
|
||||
// OpenAccount creates an account with the type and given initial deposit
|
||||
// as its balance.
|
||||
OpenAccount(context.Context, *OpenAccountRequest) (*Account, error)
|
||||
// CloseAccount closes the indicated account. An account can only be
|
||||
// closed if its balance is zero.
|
||||
CloseAccount(context.Context, *CloseAccountRequest) (*emptypb.Empty, error)
|
||||
// GetAccounts lists all accounts for the current customer.
|
||||
GetAccounts(context.Context, *emptypb.Empty) (*GetAccountsResponse, error)
|
||||
// GetTransactions streams all transactions that match the given criteria.
|
||||
// If the given start date is not specified, transactions since beginning
|
||||
// of time are included. Similarly, if the given end date is not specified,
|
||||
// transactions all the way to the presnet are included.
|
||||
GetTransactions(*GetTransactionsRequest, Bank_GetTransactionsServer) error
|
||||
// Deposit increases the balance of an account by depositing funds into it.
|
||||
Deposit(context.Context, *DepositRequest) (*BalanceResponse, error)
|
||||
// Withdraw decreases the balance of an account by withdrawing funds from it.
|
||||
Withdraw(context.Context, *WithdrawRequest) (*BalanceResponse, error)
|
||||
// Transfer moves money from one account to another. The source and destination
|
||||
// accounts can be with this bank (e.g. "local" account numbers) or can be
|
||||
// external accounts, identified by their ACH routing and account numbers.
|
||||
Transfer(context.Context, *TransferRequest) (*TransferResponse, error)
|
||||
mustEmbedUnimplementedBankServer()
|
||||
}
|
||||
|
||||
// UnimplementedBankServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedBankServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedBankServer) OpenAccount(context.Context, *OpenAccountRequest) (*Account, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OpenAccount not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) CloseAccount(context.Context, *CloseAccountRequest) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CloseAccount not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) GetAccounts(context.Context, *emptypb.Empty) (*GetAccountsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAccounts not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) GetTransactions(*GetTransactionsRequest, Bank_GetTransactionsServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method GetTransactions not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) Deposit(context.Context, *DepositRequest) (*BalanceResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Deposit not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) Withdraw(context.Context, *WithdrawRequest) (*BalanceResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Withdraw not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) Transfer(context.Context, *TransferRequest) (*TransferResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Transfer not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) mustEmbedUnimplementedBankServer() {}
|
||||
|
||||
// UnsafeBankServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to BankServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeBankServer interface {
|
||||
mustEmbedUnimplementedBankServer()
|
||||
}
|
||||
|
||||
func RegisterBankServer(s grpc.ServiceRegistrar, srv BankServer) {
|
||||
s.RegisterService(&Bank_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Bank_OpenAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OpenAccountRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).OpenAccount(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/OpenAccount",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).OpenAccount(ctx, req.(*OpenAccountRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_CloseAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CloseAccountRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).CloseAccount(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/CloseAccount",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).CloseAccount(ctx, req.(*CloseAccountRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_GetAccounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(emptypb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).GetAccounts(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/GetAccounts",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).GetAccounts(ctx, req.(*emptypb.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_GetTransactions_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(GetTransactionsRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(BankServer).GetTransactions(m, &bankGetTransactionsServer{stream})
|
||||
}
|
||||
|
||||
type Bank_GetTransactionsServer interface {
|
||||
Send(*Transaction) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type bankGetTransactionsServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *bankGetTransactionsServer) Send(m *Transaction) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _Bank_Deposit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DepositRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).Deposit(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/Deposit",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).Deposit(ctx, req.(*DepositRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_Withdraw_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(WithdrawRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).Withdraw(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/Withdraw",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).Withdraw(ctx, req.(*WithdrawRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_Transfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TransferRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).Transfer(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/Transfer",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).Transfer(ctx, req.(*TransferRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Bank_ServiceDesc is the grpc.ServiceDesc for Bank service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Bank_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Bank",
|
||||
HandlerType: (*BankServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "OpenAccount",
|
||||
Handler: _Bank_OpenAccount_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CloseAccount",
|
||||
Handler: _Bank_CloseAccount_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetAccounts",
|
||||
Handler: _Bank_GetAccounts_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Deposit",
|
||||
Handler: _Bank_Deposit_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Withdraw",
|
||||
Handler: _Bank_Withdraw_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Transfer",
|
||||
Handler: _Bank_Transfer_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "GetTransactions",
|
||||
Handler: _Bank_GetTransactions_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "bank.proto",
|
||||
}
|
||||
|
|
@ -1,20 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
// chatServer implements the Support gRPC service, for providing
|
||||
// a capability to connect customers and support agents in real-time
|
||||
// chat.
|
||||
type chatServer struct {
|
||||
UnimplementedSupportServer
|
||||
chatsBySession map[string]*session
|
||||
chatsAwaitingAgent []string
|
||||
lastSession int32
|
||||
|
|
@ -134,7 +135,7 @@ func (s *chatServer) ChatCustomer(stream Support_ChatCustomerServer) error {
|
|||
}
|
||||
|
||||
entry := &ChatEntry{
|
||||
Date: ptypes.TimestampNow(),
|
||||
Date: timestamppb.Now(),
|
||||
Entry: &ChatEntry_CustomerMsg{
|
||||
CustomerMsg: req.Msg,
|
||||
},
|
||||
|
|
@ -279,7 +280,7 @@ func (s *chatServer) ChatAgent(stream Support_ChatAgentServer) error {
|
|||
}
|
||||
|
||||
entry := &ChatEntry{
|
||||
Date: ptypes.TimestampNow(),
|
||||
Date: timestamppb.Now(),
|
||||
Entry: &ChatEntry_AgentMsg{
|
||||
AgentMsg: &AgentMessage{
|
||||
AgentName: agent,
|
||||
|
|
@ -1,14 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
// In-memory database that is periodically saved to a JSON file.
|
||||
|
|
@ -43,7 +42,7 @@ func (a *accounts) openAccount(customer string, accountType Account_Type, initia
|
|||
acct.Transactions = append(acct.Transactions, &Transaction{
|
||||
AccountNumber: num,
|
||||
SeqNumber: 1,
|
||||
Date: ptypes.TimestampNow(),
|
||||
Date: timestamppb.Now(),
|
||||
AmountCents: initialBalanceCents,
|
||||
Desc: "initial deposit",
|
||||
})
|
||||
|
|
@ -130,7 +129,7 @@ func (a *account) newTransaction(amountCents int32, desc string) (newBalance int
|
|||
a.BalanceCents = bal
|
||||
a.Transactions = append(a.Transactions, &Transaction{
|
||||
AccountNumber: a.AccountNumber,
|
||||
Date: ptypes.TimestampNow(),
|
||||
Date: timestamppb.Now(),
|
||||
AmountCents: amountCents,
|
||||
SeqNumber: uint64(len(a.Transactions) + 1),
|
||||
Desc: desc,
|
||||
|
|
@ -139,16 +138,11 @@ func (a *account) newTransaction(amountCents int32, desc string) (newBalance int
|
|||
}
|
||||
|
||||
func (t *Transaction) MarshalJSON() ([]byte, error) {
|
||||
var jsm jsonpb.Marshaler
|
||||
var buf bytes.Buffer
|
||||
if err := jsm.Marshal(&buf, t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
return protojson.Marshal(t)
|
||||
}
|
||||
|
||||
func (t *Transaction) UnmarshalJSON(b []byte) error {
|
||||
return jsonpb.Unmarshal(bytes.NewReader(b), t)
|
||||
return protojson.Unmarshal(b, t)
|
||||
}
|
||||
|
||||
func (a *accounts) clone() *accounts {
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package main
|
||||
|
||||
//go:generate protoc --go_out=plugins=grpc:./ bank.proto support.proto
|
||||
//go:generate protoc --go_out=. --go-grpc_out=. bank.proto support.proto
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
|
@ -14,7 +14,6 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/peer"
|
||||
|
|
@ -130,7 +129,7 @@ type svr struct {
|
|||
}
|
||||
|
||||
func (s *svr) load() error {
|
||||
accts, err := ioutil.ReadFile(s.datafile)
|
||||
accts, err := os.ReadFile(s.datafile)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
|
@ -162,7 +161,7 @@ func (s *svr) flush() {
|
|||
|
||||
if b, err := json.Marshal(accounts); err != nil {
|
||||
grpclog.Errorf("failed to save data to %q", s.datafile)
|
||||
} else if err := ioutil.WriteFile(s.datafile, b, 0666); err != nil {
|
||||
} else if err := os.WriteFile(s.datafile, b, 0666); err != nil {
|
||||
grpclog.Errorf("failed to save data to %q", s.datafile)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,6 @@
|
|||
syntax = "proto3";
|
||||
|
||||
option go_package = "main";
|
||||
option go_package = ".;main";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// SupportClient is the client API for Support service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type SupportClient interface {
|
||||
// ChatCustomer is used by a customer-facing app to send the customer's messages
|
||||
// to a chat session. The customer is how initiates and terminates (via "hangup")
|
||||
// a chat session. Only customers may invoke this method (e.g. requests must
|
||||
// include customer auth credentials).
|
||||
ChatCustomer(ctx context.Context, opts ...grpc.CallOption) (Support_ChatCustomerClient, error)
|
||||
// ChatAgent is used by an agent-facing app to allow an agent to reply to a
|
||||
// customer's messages in a chat session. The agent may accept a chat session,
|
||||
// which defaults to the session awaiting an agent for the longest period of time
|
||||
// (FIFO queue).
|
||||
ChatAgent(ctx context.Context, opts ...grpc.CallOption) (Support_ChatAgentClient, error)
|
||||
}
|
||||
|
||||
type supportClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewSupportClient(cc grpc.ClientConnInterface) SupportClient {
|
||||
return &supportClient{cc}
|
||||
}
|
||||
|
||||
func (c *supportClient) ChatCustomer(ctx context.Context, opts ...grpc.CallOption) (Support_ChatCustomerClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Support_ServiceDesc.Streams[0], "/Support/ChatCustomer", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &supportChatCustomerClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Support_ChatCustomerClient interface {
|
||||
Send(*ChatCustomerRequest) error
|
||||
Recv() (*ChatCustomerResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type supportChatCustomerClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *supportChatCustomerClient) Send(m *ChatCustomerRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *supportChatCustomerClient) Recv() (*ChatCustomerResponse, error) {
|
||||
m := new(ChatCustomerResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *supportClient) ChatAgent(ctx context.Context, opts ...grpc.CallOption) (Support_ChatAgentClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Support_ServiceDesc.Streams[1], "/Support/ChatAgent", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &supportChatAgentClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Support_ChatAgentClient interface {
|
||||
Send(*ChatAgentRequest) error
|
||||
Recv() (*ChatAgentResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type supportChatAgentClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *supportChatAgentClient) Send(m *ChatAgentRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *supportChatAgentClient) Recv() (*ChatAgentResponse, error) {
|
||||
m := new(ChatAgentResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// SupportServer is the server API for Support service.
|
||||
// All implementations must embed UnimplementedSupportServer
|
||||
// for forward compatibility
|
||||
type SupportServer interface {
|
||||
// ChatCustomer is used by a customer-facing app to send the customer's messages
|
||||
// to a chat session. The customer is how initiates and terminates (via "hangup")
|
||||
// a chat session. Only customers may invoke this method (e.g. requests must
|
||||
// include customer auth credentials).
|
||||
ChatCustomer(Support_ChatCustomerServer) error
|
||||
// ChatAgent is used by an agent-facing app to allow an agent to reply to a
|
||||
// customer's messages in a chat session. The agent may accept a chat session,
|
||||
// which defaults to the session awaiting an agent for the longest period of time
|
||||
// (FIFO queue).
|
||||
ChatAgent(Support_ChatAgentServer) error
|
||||
mustEmbedUnimplementedSupportServer()
|
||||
}
|
||||
|
||||
// UnimplementedSupportServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedSupportServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedSupportServer) ChatCustomer(Support_ChatCustomerServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method ChatCustomer not implemented")
|
||||
}
|
||||
func (UnimplementedSupportServer) ChatAgent(Support_ChatAgentServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method ChatAgent not implemented")
|
||||
}
|
||||
func (UnimplementedSupportServer) mustEmbedUnimplementedSupportServer() {}
|
||||
|
||||
// UnsafeSupportServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to SupportServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeSupportServer interface {
|
||||
mustEmbedUnimplementedSupportServer()
|
||||
}
|
||||
|
||||
func RegisterSupportServer(s grpc.ServiceRegistrar, srv SupportServer) {
|
||||
s.RegisterService(&Support_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Support_ChatCustomer_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(SupportServer).ChatCustomer(&supportChatCustomerServer{stream})
|
||||
}
|
||||
|
||||
type Support_ChatCustomerServer interface {
|
||||
Send(*ChatCustomerResponse) error
|
||||
Recv() (*ChatCustomerRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type supportChatCustomerServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *supportChatCustomerServer) Send(m *ChatCustomerResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *supportChatCustomerServer) Recv() (*ChatCustomerRequest, error) {
|
||||
m := new(ChatCustomerRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _Support_ChatAgent_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(SupportServer).ChatAgent(&supportChatAgentServer{stream})
|
||||
}
|
||||
|
||||
type Support_ChatAgentServer interface {
|
||||
Send(*ChatAgentResponse) error
|
||||
Recv() (*ChatAgentRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type supportChatAgentServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *supportChatAgentServer) Send(m *ChatAgentResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *supportChatAgentServer) Recv() (*ChatAgentRequest, error) {
|
||||
m := new(ChatAgentRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Support_ServiceDesc is the grpc.ServiceDesc for Support service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Support_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Support",
|
||||
HandlerType: (*SupportServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "ChatCustomer",
|
||||
Handler: _Support_ChatCustomer_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "ChatAgent",
|
||||
Handler: _Support_ChatAgent_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "support.proto",
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
|
|
@ -9,17 +10,15 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/interop/grpc_testing"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/fullstorydev/grpcurl"
|
||||
grpcurl_testing "github.com/fullstorydev/grpcurl/testing"
|
||||
grpcurl_testing "github.com/fullstorydev/grpcurl/internal/testing"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -96,7 +95,7 @@ func main() {
|
|||
|
||||
svr := grpc.NewServer(opts...)
|
||||
|
||||
grpc_testing.RegisterTestServiceServer(svr, grpcurl_testing.TestServer{})
|
||||
grpcurl_testing.RegisterTestServiceServer(svr, grpcurl_testing.TestServer{})
|
||||
if !*noreflect {
|
||||
reflection.Register(svr)
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package main
|
||||
|
|
@ -3,7 +3,7 @@ syntax = "proto3";
|
|||
import "google/protobuf/descriptor.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "testing/example2.proto";
|
||||
import "example2.proto";
|
||||
|
||||
message TestRequest {
|
||||
repeated string file_names = 1;
|
||||
Binary file not shown.
|
|
@ -0,0 +1,344 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0-devel
|
||||
// protoc v3.14.0
|
||||
// source: test_objects.proto
|
||||
|
||||
package jsonpb
|
||||
|
||||
import (
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
anypb "google.golang.org/protobuf/types/known/anypb"
|
||||
durationpb "google.golang.org/protobuf/types/known/durationpb"
|
||||
structpb "google.golang.org/protobuf/types/known/structpb"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type KnownTypes struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
An *anypb.Any `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"`
|
||||
Dur *durationpb.Duration `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"`
|
||||
St *structpb.Struct `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"`
|
||||
Ts *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"`
|
||||
Lv *structpb.ListValue `protobuf:"bytes,15,opt,name=lv" json:"lv,omitempty"`
|
||||
Val *structpb.Value `protobuf:"bytes,16,opt,name=val" json:"val,omitempty"`
|
||||
Dbl *wrapperspb.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"`
|
||||
Flt *wrapperspb.FloatValue `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"`
|
||||
I64 *wrapperspb.Int64Value `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"`
|
||||
U64 *wrapperspb.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"`
|
||||
I32 *wrapperspb.Int32Value `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"`
|
||||
U32 *wrapperspb.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"`
|
||||
Bool *wrapperspb.BoolValue `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"`
|
||||
Str *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"`
|
||||
Bytes *wrapperspb.BytesValue `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"`
|
||||
}
|
||||
|
||||
func (x *KnownTypes) Reset() {
|
||||
*x = KnownTypes{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_test_objects_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *KnownTypes) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*KnownTypes) ProtoMessage() {}
|
||||
|
||||
func (x *KnownTypes) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_test_objects_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use KnownTypes.ProtoReflect.Descriptor instead.
|
||||
func (*KnownTypes) Descriptor() ([]byte, []int) {
|
||||
return file_test_objects_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetAn() *anypb.Any {
|
||||
if x != nil {
|
||||
return x.An
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetDur() *durationpb.Duration {
|
||||
if x != nil {
|
||||
return x.Dur
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetSt() *structpb.Struct {
|
||||
if x != nil {
|
||||
return x.St
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetTs() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.Ts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetLv() *structpb.ListValue {
|
||||
if x != nil {
|
||||
return x.Lv
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetVal() *structpb.Value {
|
||||
if x != nil {
|
||||
return x.Val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetDbl() *wrapperspb.DoubleValue {
|
||||
if x != nil {
|
||||
return x.Dbl
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetFlt() *wrapperspb.FloatValue {
|
||||
if x != nil {
|
||||
return x.Flt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetI64() *wrapperspb.Int64Value {
|
||||
if x != nil {
|
||||
return x.I64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetU64() *wrapperspb.UInt64Value {
|
||||
if x != nil {
|
||||
return x.U64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetI32() *wrapperspb.Int32Value {
|
||||
if x != nil {
|
||||
return x.I32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetU32() *wrapperspb.UInt32Value {
|
||||
if x != nil {
|
||||
return x.U32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetBool() *wrapperspb.BoolValue {
|
||||
if x != nil {
|
||||
return x.Bool
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetStr() *wrapperspb.StringValue {
|
||||
if x != nil {
|
||||
return x.Str
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KnownTypes) GetBytes() *wrapperspb.BytesValue {
|
||||
if x != nil {
|
||||
return x.Bytes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_test_objects_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_test_objects_proto_rawDesc = []byte{
|
||||
0x0a, 0x12, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6a, 0x73, 0x6f, 0x6e, 0x70, 0x62, 0x1a, 0x19, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e,
|
||||
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xba, 0x05, 0x0a, 0x0a, 0x4b, 0x6e, 0x6f, 0x77, 0x6e,
|
||||
0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x02, 0x61, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x61, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x64,
|
||||
0x75, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x03, 0x64, 0x75, 0x72, 0x12, 0x27, 0x0a, 0x02, 0x73, 0x74, 0x18, 0x0c,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x02, 0x73,
|
||||
0x74, 0x12, 0x2a, 0x0a, 0x02, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x02, 0x74, 0x73, 0x12, 0x2a, 0x0a,
|
||||
0x02, 0x6c, 0x76, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74,
|
||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x02, 0x6c, 0x76, 0x12, 0x28, 0x0a, 0x03, 0x76, 0x61, 0x6c,
|
||||
0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03,
|
||||
0x76, 0x61, 0x6c, 0x12, 0x2e, 0x0a, 0x03, 0x64, 0x62, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||
0x75, 0x66, 0x2e, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03,
|
||||
0x64, 0x62, 0x6c, 0x12, 0x2d, 0x0a, 0x03, 0x66, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||
0x75, 0x66, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x66,
|
||||
0x6c, 0x74, 0x12, 0x2d, 0x0a, 0x03, 0x69, 0x36, 0x34, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x69, 0x36,
|
||||
0x34, 0x12, 0x2e, 0x0a, 0x03, 0x75, 0x36, 0x34, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x75, 0x36,
|
||||
0x34, 0x12, 0x2d, 0x0a, 0x03, 0x69, 0x33, 0x32, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x69, 0x33, 0x32,
|
||||
0x12, 0x2e, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x75, 0x33, 0x32,
|
||||
0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6c,
|
||||
0x12, 0x2e, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x73, 0x74, 0x72,
|
||||
0x12, 0x31, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x62, 0x79,
|
||||
0x74, 0x65, 0x73, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x3b, 0x6a, 0x73, 0x6f, 0x6e, 0x70, 0x62,
|
||||
}
|
||||
|
||||
var (
|
||||
file_test_objects_proto_rawDescOnce sync.Once
|
||||
file_test_objects_proto_rawDescData = file_test_objects_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_test_objects_proto_rawDescGZIP() []byte {
|
||||
file_test_objects_proto_rawDescOnce.Do(func() {
|
||||
file_test_objects_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_objects_proto_rawDescData)
|
||||
})
|
||||
return file_test_objects_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_test_objects_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_test_objects_proto_goTypes = []interface{}{
|
||||
(*KnownTypes)(nil), // 0: jsonpb.KnownTypes
|
||||
(*anypb.Any)(nil), // 1: google.protobuf.Any
|
||||
(*durationpb.Duration)(nil), // 2: google.protobuf.Duration
|
||||
(*structpb.Struct)(nil), // 3: google.protobuf.Struct
|
||||
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
|
||||
(*structpb.ListValue)(nil), // 5: google.protobuf.ListValue
|
||||
(*structpb.Value)(nil), // 6: google.protobuf.Value
|
||||
(*wrapperspb.DoubleValue)(nil), // 7: google.protobuf.DoubleValue
|
||||
(*wrapperspb.FloatValue)(nil), // 8: google.protobuf.FloatValue
|
||||
(*wrapperspb.Int64Value)(nil), // 9: google.protobuf.Int64Value
|
||||
(*wrapperspb.UInt64Value)(nil), // 10: google.protobuf.UInt64Value
|
||||
(*wrapperspb.Int32Value)(nil), // 11: google.protobuf.Int32Value
|
||||
(*wrapperspb.UInt32Value)(nil), // 12: google.protobuf.UInt32Value
|
||||
(*wrapperspb.BoolValue)(nil), // 13: google.protobuf.BoolValue
|
||||
(*wrapperspb.StringValue)(nil), // 14: google.protobuf.StringValue
|
||||
(*wrapperspb.BytesValue)(nil), // 15: google.protobuf.BytesValue
|
||||
}
|
||||
var file_test_objects_proto_depIdxs = []int32{
|
||||
1, // 0: jsonpb.KnownTypes.an:type_name -> google.protobuf.Any
|
||||
2, // 1: jsonpb.KnownTypes.dur:type_name -> google.protobuf.Duration
|
||||
3, // 2: jsonpb.KnownTypes.st:type_name -> google.protobuf.Struct
|
||||
4, // 3: jsonpb.KnownTypes.ts:type_name -> google.protobuf.Timestamp
|
||||
5, // 4: jsonpb.KnownTypes.lv:type_name -> google.protobuf.ListValue
|
||||
6, // 5: jsonpb.KnownTypes.val:type_name -> google.protobuf.Value
|
||||
7, // 6: jsonpb.KnownTypes.dbl:type_name -> google.protobuf.DoubleValue
|
||||
8, // 7: jsonpb.KnownTypes.flt:type_name -> google.protobuf.FloatValue
|
||||
9, // 8: jsonpb.KnownTypes.i64:type_name -> google.protobuf.Int64Value
|
||||
10, // 9: jsonpb.KnownTypes.u64:type_name -> google.protobuf.UInt64Value
|
||||
11, // 10: jsonpb.KnownTypes.i32:type_name -> google.protobuf.Int32Value
|
||||
12, // 11: jsonpb.KnownTypes.u32:type_name -> google.protobuf.UInt32Value
|
||||
13, // 12: jsonpb.KnownTypes.bool:type_name -> google.protobuf.BoolValue
|
||||
14, // 13: jsonpb.KnownTypes.str:type_name -> google.protobuf.StringValue
|
||||
15, // 14: jsonpb.KnownTypes.bytes:type_name -> google.protobuf.BytesValue
|
||||
15, // [15:15] is the sub-list for method output_type
|
||||
15, // [15:15] is the sub-list for method input_type
|
||||
15, // [15:15] is the sub-list for extension type_name
|
||||
15, // [15:15] is the sub-list for extension extendee
|
||||
0, // [0:15] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_test_objects_proto_init() }
|
||||
func file_test_objects_proto_init() {
|
||||
if File_test_objects_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_test_objects_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*KnownTypes); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_test_objects_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_test_objects_proto_goTypes,
|
||||
DependencyIndexes: file_test_objects_proto_depIdxs,
|
||||
MessageInfos: file_test_objects_proto_msgTypes,
|
||||
}.Build()
|
||||
File_test_objects_proto = out.File
|
||||
file_test_objects_proto_rawDesc = nil
|
||||
file_test_objects_proto_goTypes = nil
|
||||
file_test_objects_proto_depIdxs = nil
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
syntax = "proto2";
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
package jsonpb;
|
||||
|
||||
option go_package=".;jsonpb";
|
||||
|
||||
message KnownTypes {
|
||||
optional google.protobuf.Any an = 14;
|
||||
optional google.protobuf.Duration dur = 1;
|
||||
optional google.protobuf.Struct st = 12;
|
||||
optional google.protobuf.Timestamp ts = 2;
|
||||
optional google.protobuf.ListValue lv = 15;
|
||||
optional google.protobuf.Value val = 16;
|
||||
|
||||
optional google.protobuf.DoubleValue dbl = 3;
|
||||
optional google.protobuf.FloatValue flt = 4;
|
||||
optional google.protobuf.Int64Value i64 = 5;
|
||||
optional google.protobuf.UInt64Value u64 = 6;
|
||||
optional google.protobuf.Int32Value i32 = 7;
|
||||
optional google.protobuf.UInt32Value u32 = 8;
|
||||
optional google.protobuf.BoolValue bool = 9;
|
||||
optional google.protobuf.StringValue str = 10;
|
||||
optional google.protobuf.BytesValue bytes = 11;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -18,7 +18,9 @@
|
|||
// of unary/streaming requests/responses.
|
||||
syntax = "proto3";
|
||||
|
||||
package grpc.testing;
|
||||
package testing;
|
||||
|
||||
option go_package = ".;testing";
|
||||
|
||||
message Empty {}
|
||||
|
||||
|
|
@ -172,5 +174,5 @@ service TestService {
|
|||
// that case.
|
||||
service UnimplementedService {
|
||||
// A call that no server should implement
|
||||
rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty);
|
||||
rpc UnimplementedCall(Empty) returns (Empty);
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,523 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package testing
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// TestServiceClient is the client API for TestService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type TestServiceClient interface {
|
||||
// One empty request followed by one empty response.
|
||||
EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
|
||||
// One request followed by one response.
|
||||
// The server returns the client payload as-is.
|
||||
UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error)
|
||||
// One request followed by a sequence of responses (streamed download).
|
||||
// The server returns the payload with client desired type and sizes.
|
||||
StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error)
|
||||
// A sequence of requests followed by one response (streamed upload).
|
||||
// The server returns the aggregated size of client payload as the result.
|
||||
StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error)
|
||||
// A sequence of requests with each request served by the server immediately.
|
||||
// As one request could lead to multiple responses, this interface
|
||||
// demonstrates the idea of full duplexing.
|
||||
FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error)
|
||||
// A sequence of requests followed by a sequence of responses.
|
||||
// The server buffers all the client requests and then serves them in order. A
|
||||
// stream of responses are returned to the client when the server starts with
|
||||
// first request.
|
||||
HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error)
|
||||
}
|
||||
|
||||
type testServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewTestServiceClient(cc grpc.ClientConnInterface) TestServiceClient {
|
||||
return &testServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *testServiceClient) EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
|
||||
out := new(Empty)
|
||||
err := c.cc.Invoke(ctx, "/testing.TestService/EmptyCall", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) {
|
||||
out := new(SimpleResponse)
|
||||
err := c.cc.Invoke(ctx, "/testing.TestService/UnaryCall", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[0], "/testing.TestService/StreamingOutputCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceStreamingOutputCallClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_StreamingOutputCallClient interface {
|
||||
Recv() (*StreamingOutputCallResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceStreamingOutputCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingOutputCallClient) Recv() (*StreamingOutputCallResponse, error) {
|
||||
m := new(StreamingOutputCallResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[1], "/testing.TestService/StreamingInputCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceStreamingInputCallClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_StreamingInputCallClient interface {
|
||||
Send(*StreamingInputCallRequest) error
|
||||
CloseAndRecv() (*StreamingInputCallResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceStreamingInputCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingInputCallClient) Send(m *StreamingInputCallRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingInputCallClient) CloseAndRecv() (*StreamingInputCallResponse, error) {
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := new(StreamingInputCallResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[2], "/testing.TestService/FullDuplexCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceFullDuplexCallClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_FullDuplexCallClient interface {
|
||||
Send(*StreamingOutputCallRequest) error
|
||||
Recv() (*StreamingOutputCallResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceFullDuplexCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
|
||||
m := new(StreamingOutputCallResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[3], "/testing.TestService/HalfDuplexCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceHalfDuplexCallClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_HalfDuplexCallClient interface {
|
||||
Send(*StreamingOutputCallRequest) error
|
||||
Recv() (*StreamingOutputCallResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceHalfDuplexCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceHalfDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
|
||||
m := new(StreamingOutputCallResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// TestServiceServer is the server API for TestService service.
|
||||
// All implementations must embed UnimplementedTestServiceServer
|
||||
// for forward compatibility
|
||||
type TestServiceServer interface {
|
||||
// One empty request followed by one empty response.
|
||||
EmptyCall(context.Context, *Empty) (*Empty, error)
|
||||
// One request followed by one response.
|
||||
// The server returns the client payload as-is.
|
||||
UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error)
|
||||
// One request followed by a sequence of responses (streamed download).
|
||||
// The server returns the payload with client desired type and sizes.
|
||||
StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error
|
||||
// A sequence of requests followed by one response (streamed upload).
|
||||
// The server returns the aggregated size of client payload as the result.
|
||||
StreamingInputCall(TestService_StreamingInputCallServer) error
|
||||
// A sequence of requests with each request served by the server immediately.
|
||||
// As one request could lead to multiple responses, this interface
|
||||
// demonstrates the idea of full duplexing.
|
||||
FullDuplexCall(TestService_FullDuplexCallServer) error
|
||||
// A sequence of requests followed by a sequence of responses.
|
||||
// The server buffers all the client requests and then serves them in order. A
|
||||
// stream of responses are returned to the client when the server starts with
|
||||
// first request.
|
||||
HalfDuplexCall(TestService_HalfDuplexCallServer) error
|
||||
mustEmbedUnimplementedTestServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedTestServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedTestServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedTestServiceServer) EmptyCall(context.Context, *Empty) (*Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method EmptyCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnaryCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method StreamingOutputCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) StreamingInputCall(TestService_StreamingInputCallServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method StreamingInputCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) FullDuplexCall(TestService_FullDuplexCallServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method FullDuplexCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) HalfDuplexCall(TestService_HalfDuplexCallServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method HalfDuplexCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) mustEmbedUnimplementedTestServiceServer() {}
|
||||
|
||||
// UnsafeTestServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to TestServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeTestServiceServer interface {
|
||||
mustEmbedUnimplementedTestServiceServer()
|
||||
}
|
||||
|
||||
func RegisterTestServiceServer(s grpc.ServiceRegistrar, srv TestServiceServer) {
|
||||
s.RegisterService(&TestService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServiceServer).EmptyCall(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/testing.TestService/EmptyCall",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServiceServer).EmptyCall(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SimpleRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServiceServer).UnaryCall(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/testing.TestService/UnaryCall",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServiceServer).UnaryCall(ctx, req.(*SimpleRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TestService_StreamingOutputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(StreamingOutputCallRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(TestServiceServer).StreamingOutputCall(m, &testServiceStreamingOutputCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_StreamingOutputCallServer interface {
|
||||
Send(*StreamingOutputCallResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceStreamingOutputCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingOutputCallServer) Send(m *StreamingOutputCallResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _TestService_StreamingInputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).StreamingInputCall(&testServiceStreamingInputCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_StreamingInputCallServer interface {
|
||||
SendAndClose(*StreamingInputCallResponse) error
|
||||
Recv() (*StreamingInputCallRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceStreamingInputCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingInputCallServer) SendAndClose(m *StreamingInputCallResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingInputCallServer) Recv() (*StreamingInputCallRequest, error) {
|
||||
m := new(StreamingInputCallRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _TestService_FullDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).FullDuplexCall(&testServiceFullDuplexCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_FullDuplexCallServer interface {
|
||||
Send(*StreamingOutputCallResponse) error
|
||||
Recv() (*StreamingOutputCallRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceFullDuplexCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
|
||||
m := new(StreamingOutputCallRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _TestService_HalfDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).HalfDuplexCall(&testServiceHalfDuplexCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_HalfDuplexCallServer interface {
|
||||
Send(*StreamingOutputCallResponse) error
|
||||
Recv() (*StreamingOutputCallRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceHalfDuplexCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceHalfDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceHalfDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
|
||||
m := new(StreamingOutputCallRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// TestService_ServiceDesc is the grpc.ServiceDesc for TestService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var TestService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "testing.TestService",
|
||||
HandlerType: (*TestServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "EmptyCall",
|
||||
Handler: _TestService_EmptyCall_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "UnaryCall",
|
||||
Handler: _TestService_UnaryCall_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "StreamingOutputCall",
|
||||
Handler: _TestService_StreamingOutputCall_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "StreamingInputCall",
|
||||
Handler: _TestService_StreamingInputCall_Handler,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "FullDuplexCall",
|
||||
Handler: _TestService_FullDuplexCall_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "HalfDuplexCall",
|
||||
Handler: _TestService_HalfDuplexCall_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "test.proto",
|
||||
}
|
||||
|
||||
// UnimplementedServiceClient is the client API for UnimplementedService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type UnimplementedServiceClient interface {
|
||||
// A call that no server should implement
|
||||
UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
|
||||
}
|
||||
|
||||
type unimplementedServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewUnimplementedServiceClient(cc grpc.ClientConnInterface) UnimplementedServiceClient {
|
||||
return &unimplementedServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *unimplementedServiceClient) UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
|
||||
out := new(Empty)
|
||||
err := c.cc.Invoke(ctx, "/testing.UnimplementedService/UnimplementedCall", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// UnimplementedServiceServer is the server API for UnimplementedService service.
|
||||
// All implementations must embed UnimplementedUnimplementedServiceServer
|
||||
// for forward compatibility
|
||||
type UnimplementedServiceServer interface {
|
||||
// A call that no server should implement
|
||||
UnimplementedCall(context.Context, *Empty) (*Empty, error)
|
||||
mustEmbedUnimplementedUnimplementedServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedUnimplementedServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedUnimplementedServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedUnimplementedServiceServer) UnimplementedCall(context.Context, *Empty) (*Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnimplementedCall not implemented")
|
||||
}
|
||||
func (UnimplementedUnimplementedServiceServer) mustEmbedUnimplementedUnimplementedServiceServer() {}
|
||||
|
||||
// UnsafeUnimplementedServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to UnimplementedServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeUnimplementedServiceServer interface {
|
||||
mustEmbedUnimplementedUnimplementedServiceServer()
|
||||
}
|
||||
|
||||
func RegisterUnimplementedServiceServer(s grpc.ServiceRegistrar, srv UnimplementedServiceServer) {
|
||||
s.RegisterService(&UnimplementedService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _UnimplementedService_UnimplementedCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UnimplementedServiceServer).UnimplementedCall(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/testing.UnimplementedService/UnimplementedCall",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UnimplementedServiceServer).UnimplementedCall(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// UnimplementedService_ServiceDesc is the grpc.ServiceDesc for UnimplementedService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var UnimplementedService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "testing.UnimplementedService",
|
||||
HandlerType: (*UnimplementedServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "UnimplementedCall",
|
||||
Handler: _UnimplementedService_UnimplementedCall_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "test.proto",
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
package testing
|
||||
|
||||
//go:generate protoc --go_out=. --go-grpc_out=. test.proto
|
||||
//go:generate protoc --descriptor_set_out=./test.protoset test.proto
|
||||
//go:generate protoc --descriptor_set_out=./example.protoset --include_imports example.proto
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/interop/grpc_testing"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
|
|
@ -16,10 +19,12 @@ import (
|
|||
)
|
||||
|
||||
// TestServer implements the TestService interface defined in example.proto.
|
||||
type TestServer struct{}
|
||||
type TestServer struct {
|
||||
UnimplementedTestServiceServer
|
||||
}
|
||||
|
||||
// EmptyCall accepts one empty request and issues one empty response.
|
||||
func (TestServer) EmptyCall(ctx context.Context, req *grpc_testing.Empty) (*grpc_testing.Empty, error) {
|
||||
func (TestServer) EmptyCall(ctx context.Context, req *Empty) (*Empty, error) {
|
||||
headers, trailers, failEarly, failLate := processMetadata(ctx)
|
||||
grpc.SetHeader(ctx, headers)
|
||||
grpc.SetTrailer(ctx, trailers)
|
||||
|
|
@ -35,7 +40,7 @@ func (TestServer) EmptyCall(ctx context.Context, req *grpc_testing.Empty) (*grpc
|
|||
|
||||
// UnaryCall accepts one request and issues one response. The response includes
|
||||
// the client's payload as-is.
|
||||
func (TestServer) UnaryCall(ctx context.Context, req *grpc_testing.SimpleRequest) (*grpc_testing.SimpleResponse, error) {
|
||||
func (TestServer) UnaryCall(ctx context.Context, req *SimpleRequest) (*SimpleResponse, error) {
|
||||
headers, trailers, failEarly, failLate := processMetadata(ctx)
|
||||
grpc.SetHeader(ctx, headers)
|
||||
grpc.SetTrailer(ctx, trailers)
|
||||
|
|
@ -46,7 +51,7 @@ func (TestServer) UnaryCall(ctx context.Context, req *grpc_testing.SimpleRequest
|
|||
return nil, status.Error(failLate, "fail")
|
||||
}
|
||||
|
||||
return &grpc_testing.SimpleResponse{
|
||||
return &SimpleResponse{
|
||||
Payload: req.Payload,
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -54,7 +59,7 @@ func (TestServer) UnaryCall(ctx context.Context, req *grpc_testing.SimpleRequest
|
|||
// StreamingOutputCall accepts one request and issues a sequence of responses
|
||||
// (streamed download). The server returns the payload with client desired type
|
||||
// and sizes as specified in the request's ResponseParameters.
|
||||
func (TestServer) StreamingOutputCall(req *grpc_testing.StreamingOutputCallRequest, str grpc_testing.TestService_StreamingOutputCallServer) error {
|
||||
func (TestServer) StreamingOutputCall(req *StreamingOutputCallRequest, str TestService_StreamingOutputCallServer) error {
|
||||
headers, trailers, failEarly, failLate := processMetadata(str.Context())
|
||||
str.SetHeader(headers)
|
||||
str.SetTrailer(trailers)
|
||||
|
|
@ -62,7 +67,7 @@ func (TestServer) StreamingOutputCall(req *grpc_testing.StreamingOutputCallReque
|
|||
return status.Error(failEarly, "fail")
|
||||
}
|
||||
|
||||
rsp := &grpc_testing.StreamingOutputCallResponse{Payload: &grpc_testing.Payload{}}
|
||||
rsp := &StreamingOutputCallResponse{Payload: &Payload{}}
|
||||
for _, param := range req.ResponseParameters {
|
||||
if str.Context().Err() != nil {
|
||||
return str.Context().Err()
|
||||
|
|
@ -92,7 +97,7 @@ func (TestServer) StreamingOutputCall(req *grpc_testing.StreamingOutputCallReque
|
|||
// StreamingInputCall accepts a sequence of requests and issues one response
|
||||
// (streamed upload). The server returns the aggregated size of client payloads
|
||||
// as the result.
|
||||
func (TestServer) StreamingInputCall(str grpc_testing.TestService_StreamingInputCallServer) error {
|
||||
func (TestServer) StreamingInputCall(str TestService_StreamingInputCallServer) error {
|
||||
headers, trailers, failEarly, failLate := processMetadata(str.Context())
|
||||
str.SetHeader(headers)
|
||||
str.SetTrailer(trailers)
|
||||
|
|
@ -114,7 +119,7 @@ func (TestServer) StreamingInputCall(str grpc_testing.TestService_StreamingInput
|
|||
sz += len(req.Payload.Body)
|
||||
}
|
||||
}
|
||||
if err := str.SendAndClose(&grpc_testing.StreamingInputCallResponse{AggregatedPayloadSize: int32(sz)}); err != nil {
|
||||
if err := str.SendAndClose(&StreamingInputCallResponse{AggregatedPayloadSize: int32(sz)}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -127,7 +132,7 @@ func (TestServer) StreamingInputCall(str grpc_testing.TestService_StreamingInput
|
|||
// FullDuplexCall accepts a sequence of requests with each request served by the
|
||||
// server immediately. As one request could lead to multiple responses, this
|
||||
// interface demonstrates the idea of full duplexing.
|
||||
func (TestServer) FullDuplexCall(str grpc_testing.TestService_FullDuplexCallServer) error {
|
||||
func (TestServer) FullDuplexCall(str TestService_FullDuplexCallServer) error {
|
||||
headers, trailers, failEarly, failLate := processMetadata(str.Context())
|
||||
str.SetHeader(headers)
|
||||
str.SetTrailer(trailers)
|
||||
|
|
@ -135,7 +140,7 @@ func (TestServer) FullDuplexCall(str grpc_testing.TestService_FullDuplexCallServ
|
|||
return status.Error(failEarly, "fail")
|
||||
}
|
||||
|
||||
rsp := &grpc_testing.StreamingOutputCallResponse{Payload: &grpc_testing.Payload{}}
|
||||
rsp := &StreamingOutputCallResponse{Payload: &Payload{}}
|
||||
for {
|
||||
if str.Context().Err() != nil {
|
||||
return str.Context().Err()
|
||||
|
|
@ -170,7 +175,7 @@ func (TestServer) FullDuplexCall(str grpc_testing.TestService_FullDuplexCallServ
|
|||
// responses. The server buffers all the client requests and then serves them
|
||||
// in order. A stream of responses is returned to the client once the client
|
||||
// half-closes the stream.
|
||||
func (TestServer) HalfDuplexCall(str grpc_testing.TestService_HalfDuplexCallServer) error {
|
||||
func (TestServer) HalfDuplexCall(str TestService_HalfDuplexCallServer) error {
|
||||
headers, trailers, failEarly, failLate := processMetadata(str.Context())
|
||||
str.SetHeader(headers)
|
||||
str.SetTrailer(trailers)
|
||||
|
|
@ -178,7 +183,7 @@ func (TestServer) HalfDuplexCall(str grpc_testing.TestService_HalfDuplexCallServ
|
|||
return status.Error(failEarly, "fail")
|
||||
}
|
||||
|
||||
var reqs []*grpc_testing.StreamingOutputCallRequest
|
||||
var reqs []*StreamingOutputCallRequest
|
||||
for {
|
||||
if str.Context().Err() != nil {
|
||||
return str.Context().Err()
|
||||
|
|
@ -192,7 +197,7 @@ func (TestServer) HalfDuplexCall(str grpc_testing.TestService_HalfDuplexCallServ
|
|||
reqs = append(reqs, req)
|
||||
}
|
||||
}
|
||||
rsp := &grpc_testing.StreamingOutputCallResponse{}
|
||||
rsp := &StreamingOutputCallResponse{}
|
||||
for _, req := range reqs {
|
||||
rsp.Payload = req.Payload
|
||||
if err := str.Send(rsp); err != nil {
|
||||
|
|
@ -251,4 +256,4 @@ func toCode(vals []string) codes.Code {
|
|||
return codes.Code(i)
|
||||
}
|
||||
|
||||
var _ grpc_testing.TestServiceServer = TestServer{}
|
||||
var _ TestServiceServer = TestServer{}
|
||||
50
invoke.go
50
invoke.go
|
|
@ -2,19 +2,19 @@ package grpcurl
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/dynamic"
|
||||
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 we have to import these because some of their types appear in exported API
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/dynamic" //lint:ignore SA1019 same as above
|
||||
"github.com/jhump/protoreflect/dynamic/grpcdynamic"
|
||||
"github.com/jhump/protoreflect/grpcreflect"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
|
@ -93,9 +93,17 @@ func InvokeRPC(ctx context.Context, source DescriptorSource, ch grpcdynamic.Chan
|
|||
if svc == "" || mth == "" {
|
||||
return fmt.Errorf("given method name %q is not in expected format: 'service/method' or 'service.method'", methodName)
|
||||
}
|
||||
|
||||
dsc, err := source.FindSymbol(svc)
|
||||
if err != nil {
|
||||
if isNotFoundError(err) {
|
||||
// return a gRPC status error if hasStatus is true
|
||||
errStatus, hasStatus := status.FromError(err)
|
||||
switch {
|
||||
case hasStatus && isNotFoundError(err):
|
||||
return status.Errorf(errStatus.Code(), "target server does not expose service %q: %s", svc, errStatus.Message())
|
||||
case hasStatus:
|
||||
return status.Errorf(errStatus.Code(), "failed to query for service descriptor %q: %s", svc, errStatus.Message())
|
||||
case isNotFoundError(err):
|
||||
return fmt.Errorf("target server does not expose service %q", svc)
|
||||
}
|
||||
return fmt.Errorf("failed to query for service descriptor %q: %v", svc, err)
|
||||
|
|
@ -219,15 +227,19 @@ func invokeClientStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
|
|||
return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err)
|
||||
}
|
||||
|
||||
if respHeaders, err := str.Header(); err == nil {
|
||||
handler.OnReceiveHeaders(respHeaders)
|
||||
if str != nil {
|
||||
if respHeaders, err := str.Header(); err == nil {
|
||||
handler.OnReceiveHeaders(respHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
if stat.Code() == codes.OK {
|
||||
handler.OnReceiveResponse(resp)
|
||||
}
|
||||
|
||||
handler.OnReceiveTrailers(stat, str.Trailer())
|
||||
if str != nil {
|
||||
handler.OnReceiveTrailers(stat, str.Trailer())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -252,8 +264,10 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
|
|||
// Now we can actually invoke the RPC!
|
||||
str, err := stub.InvokeRpcServerStream(ctx, md, req)
|
||||
|
||||
if respHeaders, err := str.Header(); err == nil {
|
||||
handler.OnReceiveHeaders(respHeaders)
|
||||
if str != nil {
|
||||
if respHeaders, err := str.Header(); err == nil {
|
||||
handler.OnReceiveHeaders(respHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
// Download each response message
|
||||
|
|
@ -276,7 +290,9 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
|
|||
return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err)
|
||||
}
|
||||
|
||||
handler.OnReceiveTrailers(stat, str.Trailer())
|
||||
if str != nil {
|
||||
handler.OnReceiveTrailers(stat, str.Trailer())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -326,8 +342,10 @@ func invokeBidi(ctx context.Context, stub grpcdynamic.Stub, md *desc.MethodDescr
|
|||
}()
|
||||
}
|
||||
|
||||
if respHeaders, err := str.Header(); err == nil {
|
||||
handler.OnReceiveHeaders(respHeaders)
|
||||
if str != nil {
|
||||
if respHeaders, err := str.Header(); err == nil {
|
||||
handler.OnReceiveHeaders(respHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
// Download each response message
|
||||
|
|
@ -354,7 +372,9 @@ func invokeBidi(ctx context.Context, stub grpcdynamic.Stub, md *desc.MethodDescr
|
|||
return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err)
|
||||
}
|
||||
|
||||
handler.OnReceiveTrailers(stat, str.Trailer())
|
||||
if str != nil {
|
||||
handler.OnReceiveTrailers(stat, str.Trailer())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,18 +53,7 @@ This will create the release in GitHub with provisional release notes that just
|
|||
|
||||
### Docker Hub Releases
|
||||
|
||||
To re-run only the Docker Hub release steps, we need to build an image with the right tag and then push to Docker Hub.
|
||||
|
||||
```sh
|
||||
# from the root of the repo
|
||||
echo v2.3.4 > VERSION
|
||||
docker build -t fullstorydev/grpcurl:v2.3.4 .
|
||||
# now that we have it built, push to Docker Hub
|
||||
docker push fullstorydev/grpcurl:v2.3.4
|
||||
# push "latest" tag, too
|
||||
docker tag fullstorydev/grpcurl:v2.3.4 fullstorydev/grpcurl:latest
|
||||
docker push fullstorydev/grpcurl:latest
|
||||
```
|
||||
To re-run only the Docker Hub release steps, you can manually run through each step in the "Docker" section of `do_release.sh`.
|
||||
|
||||
If the `docker push ...` steps fail, you may need to run `docker login`, enter your Docker Hub login credentials, and then try to push again.
|
||||
|
||||
|
|
@ -74,7 +63,7 @@ The last step is to update the Homebrew recipe to use the latest version. First,
|
|||
|
||||
```sh
|
||||
# download the source archive from GitHub
|
||||
URL=https://github.com/fullstorydev/grpcurl/archive/v2.3.4.tar.gz
|
||||
URL=https://github.com/fullstorydev/grpcurl/archive/refs/tags/v2.3.4.tar.gz
|
||||
curl -L -o tmp.tgz $URL
|
||||
# and compute the SHA
|
||||
SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')"
|
||||
|
|
|
|||
|
|
@ -40,16 +40,22 @@ $PREFIX git checkout go.mod go.sum
|
|||
# if there are no valid current credentials.
|
||||
$PREFIX docker login
|
||||
echo "$VERSION" > VERSION
|
||||
$PREFIX docker build -t "fullstorydev/grpcurl:${VERSION}" .
|
||||
rm VERSION
|
||||
|
||||
# Docker Buildx support is included in Docker 19.03
|
||||
# Below step installs emulators for different architectures on the host
|
||||
# This enables running and building containers for below architectures mentioned using --platforms
|
||||
$PREFIX docker run --privileged --rm tonistiigi/binfmt:qemu-v6.1.0 --install all
|
||||
# Create a new builder instance
|
||||
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
$PREFIX docker buildx create --use --name multiarch-builder --node multiarch-builder0
|
||||
# push to docker hub, both the given version as a tag and for "latest" tag
|
||||
$PREFIX docker push "fullstorydev/grpcurl:${VERSION}"
|
||||
$PREFIX docker tag "fullstorydev/grpcurl:${VERSION}" fullstorydev/grpcurl:latest
|
||||
$PREFIX docker push fullstorydev/grpcurl:latest
|
||||
$PREFIX docker buildx build --platform linux/amd64,linux/s390x,linux/arm64,linux/ppc64le --tag fullstorydev/grpcurl:${VERSION} --tag fullstorydev/grpcurl:latest --push --progress plain --no-cache .
|
||||
$PREFIX docker buildx build --platform linux/amd64,linux/s390x,linux/arm64,linux/ppc64le --tag fullstorydev/grpcurl:${VERSION}-alpine --tag fullstorydev/grpcurl:latest-alpine --push --progress plain --no-cache --target alpine .
|
||||
rm VERSION
|
||||
|
||||
# Homebrew release
|
||||
|
||||
URL="https://github.com/fullstorydev/grpcurl/archive/${VERSION}.tar.gz"
|
||||
URL="https://github.com/fullstorydev/grpcurl/archive/refs/tags/${VERSION}.tar.gz"
|
||||
curl -L -o tmp.tgz "$URL"
|
||||
SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')"
|
||||
rm tmp.tgz
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
# packing and releasing
|
||||
To pack the current branch to a snap package:
|
||||
|
||||
`snapcraft pack`
|
||||
|
||||
To install the package locally:
|
||||
|
||||
`snap install ./grpcurl_v[version tag]_amd64.snap --devmode`
|
||||
|
||||
To upload the snap to the edge channel:
|
||||
|
||||
`snapcraft upload --release edge ./grpcurl_v[version tag]_amd64.snap`
|
||||
|
||||
(you need to own the package name registration for this!)
|
||||
|
||||
# ownership
|
||||
The snap's current owner is `pietro.pasotti@canonical.com`; who is very happy to support with maintaining the snap distribution and/or transfer its ownership to the developers.
|
||||
|
||||
Please reach out to me for questions regarding the snap; including:
|
||||
- adding support for other architectures
|
||||
- automating the release
|
||||
|
||||
Cheers and thanks for the awesome tool!
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
name: grpcurl
|
||||
base: core24
|
||||
# allow grpcurl part to call craftctl set-version
|
||||
adopt-info: grpcurl
|
||||
summary: grpcurl is a command-line tool that lets you interact with gRPC servers.
|
||||
|
||||
description: |
|
||||
grpcurl is a command-line tool that lets you interact with gRPC servers.
|
||||
It's basically curl for gRPC servers.
|
||||
|
||||
grade: stable
|
||||
confinement: strict
|
||||
license: MIT
|
||||
|
||||
platforms:
|
||||
amd64:
|
||||
build-on:
|
||||
- amd64
|
||||
build-for:
|
||||
- amd64
|
||||
arm64:
|
||||
build-on:
|
||||
- amd64
|
||||
- arm64
|
||||
build-for:
|
||||
- arm64
|
||||
|
||||
apps:
|
||||
grpcurl:
|
||||
command: grpcurl
|
||||
plugs:
|
||||
- network
|
||||
|
||||
parts:
|
||||
grpcurl:
|
||||
plugin: go
|
||||
build-snaps: [go/latest/stable]
|
||||
source: https://github.com/fullstorydev/grpcurl
|
||||
source-type: git
|
||||
override-build: |
|
||||
tag="$(git describe --tags --abbrev=0)"
|
||||
craftctl set version="$tag"
|
||||
|
||||
go build -o $CRAFT_PART_INSTALL/grpcurl ./cmd/grpcurl/grpcurl.go
|
||||
|
||||
# adjust the permissions
|
||||
chmod 0755 $CRAFT_PART_INSTALL/grpcurl
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,215 +0,0 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: testing/jsonpb_test_proto/test_objects.proto
|
||||
|
||||
package jsonpb
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
any "github.com/golang/protobuf/ptypes/any"
|
||||
duration "github.com/golang/protobuf/ptypes/duration"
|
||||
_struct "github.com/golang/protobuf/ptypes/struct"
|
||||
timestamp "github.com/golang/protobuf/ptypes/timestamp"
|
||||
wrappers "github.com/golang/protobuf/ptypes/wrappers"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type KnownTypes struct {
|
||||
An *any.Any `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"`
|
||||
Dur *duration.Duration `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"`
|
||||
St *_struct.Struct `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"`
|
||||
Ts *timestamp.Timestamp `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"`
|
||||
Lv *_struct.ListValue `protobuf:"bytes,15,opt,name=lv" json:"lv,omitempty"`
|
||||
Val *_struct.Value `protobuf:"bytes,16,opt,name=val" json:"val,omitempty"`
|
||||
Dbl *wrappers.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"`
|
||||
Flt *wrappers.FloatValue `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"`
|
||||
I64 *wrappers.Int64Value `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"`
|
||||
U64 *wrappers.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"`
|
||||
I32 *wrappers.Int32Value `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"`
|
||||
U32 *wrappers.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"`
|
||||
Bool *wrappers.BoolValue `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"`
|
||||
Str *wrappers.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"`
|
||||
Bytes *wrappers.BytesValue `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *KnownTypes) Reset() { *m = KnownTypes{} }
|
||||
func (m *KnownTypes) String() string { return proto.CompactTextString(m) }
|
||||
func (*KnownTypes) ProtoMessage() {}
|
||||
func (*KnownTypes) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ab4422ec10550c41, []int{0}
|
||||
}
|
||||
|
||||
func (m *KnownTypes) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_KnownTypes.Unmarshal(m, b)
|
||||
}
|
||||
func (m *KnownTypes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_KnownTypes.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *KnownTypes) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_KnownTypes.Merge(m, src)
|
||||
}
|
||||
func (m *KnownTypes) XXX_Size() int {
|
||||
return xxx_messageInfo_KnownTypes.Size(m)
|
||||
}
|
||||
func (m *KnownTypes) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_KnownTypes.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_KnownTypes proto.InternalMessageInfo
|
||||
|
||||
func (m *KnownTypes) GetAn() *any.Any {
|
||||
if m != nil {
|
||||
return m.An
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetDur() *duration.Duration {
|
||||
if m != nil {
|
||||
return m.Dur
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetSt() *_struct.Struct {
|
||||
if m != nil {
|
||||
return m.St
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetTs() *timestamp.Timestamp {
|
||||
if m != nil {
|
||||
return m.Ts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetLv() *_struct.ListValue {
|
||||
if m != nil {
|
||||
return m.Lv
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetVal() *_struct.Value {
|
||||
if m != nil {
|
||||
return m.Val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetDbl() *wrappers.DoubleValue {
|
||||
if m != nil {
|
||||
return m.Dbl
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetFlt() *wrappers.FloatValue {
|
||||
if m != nil {
|
||||
return m.Flt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetI64() *wrappers.Int64Value {
|
||||
if m != nil {
|
||||
return m.I64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetU64() *wrappers.UInt64Value {
|
||||
if m != nil {
|
||||
return m.U64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetI32() *wrappers.Int32Value {
|
||||
if m != nil {
|
||||
return m.I32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetU32() *wrappers.UInt32Value {
|
||||
if m != nil {
|
||||
return m.U32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetBool() *wrappers.BoolValue {
|
||||
if m != nil {
|
||||
return m.Bool
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetStr() *wrappers.StringValue {
|
||||
if m != nil {
|
||||
return m.Str
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetBytes() *wrappers.BytesValue {
|
||||
if m != nil {
|
||||
return m.Bytes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*KnownTypes)(nil), "jsonpb.KnownTypes")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("testing/jsonpb_test_proto/test_objects.proto", fileDescriptor_ab4422ec10550c41)
|
||||
}
|
||||
|
||||
var fileDescriptor_ab4422ec10550c41 = []byte{
|
||||
// 402 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0xd0, 0xdf, 0x6b, 0xd5, 0x30,
|
||||
0x14, 0x07, 0x70, 0x96, 0xee, 0x4e, 0xcd, 0x44, 0x25, 0x88, 0x66, 0xd7, 0xa1, 0x22, 0x82, 0xc3,
|
||||
0x1f, 0x2d, 0xb6, 0xa5, 0xef, 0x0e, 0x11, 0x44, 0x9f, 0xba, 0xe9, 0xeb, 0x48, 0xd6, 0xac, 0x74,
|
||||
0x64, 0x49, 0x49, 0x4e, 0xee, 0xe8, 0xbf, 0xe6, 0x5f, 0x27, 0x49, 0x73, 0x45, 0x6e, 0xc9, 0xde,
|
||||
0xee, 0xcd, 0xf7, 0x73, 0xbe, 0x9c, 0x53, 0xfc, 0x11, 0x84, 0x85, 0x41, 0xf5, 0xc5, 0xb5, 0xd5,
|
||||
0x6a, 0xe4, 0x17, 0xfe, 0xef, 0xc5, 0x68, 0x34, 0xe8, 0x22, 0xfc, 0xd4, 0xfc, 0x5a, 0x5c, 0x82,
|
||||
0xcd, 0xc3, 0x13, 0x39, 0x98, 0xd5, 0xfa, 0xa8, 0xd7, 0xba, 0x97, 0xa2, 0x08, 0xaf, 0xdc, 0x5d,
|
||||
0x15, 0x4c, 0x4d, 0x33, 0x59, 0xbf, 0xdc, 0x8d, 0x3a, 0x67, 0x18, 0x0c, 0x5a, 0xc5, 0xfc, 0x78,
|
||||
0x37, 0xb7, 0x60, 0xdc, 0x25, 0xc4, 0xf4, 0xd5, 0x6e, 0x0a, 0xc3, 0x8d, 0xb0, 0xc0, 0x6e, 0xc6,
|
||||
0x54, 0xfd, 0xad, 0x61, 0xe3, 0x28, 0x4c, 0xdc, 0xf0, 0xcd, 0x9f, 0x15, 0xc6, 0x3f, 0x94, 0xbe,
|
||||
0x55, 0xe7, 0xd3, 0x28, 0x2c, 0x79, 0x8b, 0x11, 0x53, 0xf4, 0xd1, 0xeb, 0xbd, 0x93, 0xc3, 0xf2,
|
||||
0x69, 0x3e, 0xcf, 0xe6, 0xdb, 0xd9, 0xfc, 0x8b, 0x9a, 0x5a, 0xc4, 0x14, 0xf9, 0x80, 0xb3, 0xce,
|
||||
0x19, 0xba, 0x17, 0xd8, 0xd1, 0x82, 0x7d, 0x8d, 0x17, 0xb4, 0x5e, 0x91, 0x77, 0x18, 0x59, 0xa0,
|
||||
0x0f, 0x83, 0x7d, 0xbe, 0xb0, 0x67, 0xe1, 0x9a, 0x16, 0x59, 0x20, 0xef, 0x31, 0x02, 0x4b, 0x51,
|
||||
0x80, 0xeb, 0x05, 0x3c, 0xdf, 0x1e, 0xd6, 0x22, 0xb0, 0xde, 0xca, 0x0d, 0x7d, 0x9c, 0xb0, 0x3f,
|
||||
0x07, 0x0b, 0xbf, 0x99, 0x74, 0xa2, 0x45, 0x72, 0x43, 0x4e, 0x70, 0xb6, 0x61, 0x92, 0x3e, 0x09,
|
||||
0xf8, 0xd9, 0x02, 0xcf, 0xd0, 0x13, 0x92, 0xe3, 0xac, 0xe3, 0x92, 0x66, 0x41, 0x1e, 0x2f, 0xef,
|
||||
0xd2, 0x8e, 0x4b, 0x11, 0x7d, 0xc7, 0x25, 0xf9, 0x84, 0xb3, 0x2b, 0x09, 0x74, 0x3f, 0xf8, 0x17,
|
||||
0x0b, 0xff, 0x4d, 0x6a, 0x16, 0xf7, 0xf0, 0xce, 0xf3, 0xa1, 0xa9, 0xe9, 0x2a, 0xc1, 0xbf, 0x2b,
|
||||
0x68, 0xea, 0xc8, 0x87, 0xa6, 0xf6, 0xdb, 0xb8, 0xa6, 0xa6, 0x07, 0x89, 0x6d, 0x7e, 0xfd, 0xef,
|
||||
0x5d, 0x53, 0x87, 0xfa, 0xaa, 0xa4, 0xf7, 0xd2, 0xf5, 0x55, 0xb9, 0xad, 0xaf, 0xca, 0x50, 0x5f,
|
||||
0x95, 0xf4, 0xfe, 0x1d, 0xf5, 0xff, 0xbc, 0x0b, 0x7e, 0x9f, 0x6b, 0x2d, 0xe9, 0x83, 0xc4, 0x47,
|
||||
0x3f, 0xd5, 0x5a, 0xce, 0x3c, 0x38, 0xdf, 0x6f, 0xc1, 0x50, 0x9c, 0xe8, 0x3f, 0x03, 0x33, 0xa8,
|
||||
0x3e, 0xf6, 0x5b, 0x30, 0xe4, 0x33, 0x5e, 0xf1, 0x09, 0x84, 0xa5, 0x87, 0x89, 0x03, 0x4e, 0x7d,
|
||||
0x3a, 0x0f, 0xcc, 0xf2, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xab, 0x65, 0x99, 0x5a, 0x8d, 0x03,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
package jsonpb;
|
||||
|
||||
message KnownTypes {
|
||||
optional google.protobuf.Any an = 14;
|
||||
optional google.protobuf.Duration dur = 1;
|
||||
optional google.protobuf.Struct st = 12;
|
||||
optional google.protobuf.Timestamp ts = 2;
|
||||
optional google.protobuf.ListValue lv = 15;
|
||||
optional google.protobuf.Value val = 16;
|
||||
|
||||
optional google.protobuf.DoubleValue dbl = 3;
|
||||
optional google.protobuf.FloatValue flt = 4;
|
||||
optional google.protobuf.Int64Value i64 = 5;
|
||||
optional google.protobuf.UInt64Value u64 = 6;
|
||||
optional google.protobuf.Int32Value i32 = 7;
|
||||
optional google.protobuf.UInt32Value u32 = 8;
|
||||
optional google.protobuf.BoolValue bool = 9;
|
||||
optional google.protobuf.StringValue str = 10;
|
||||
optional google.protobuf.BytesValue bytes = 11;
|
||||
}
|
||||
Binary file not shown.
|
|
@ -1,19 +1,18 @@
|
|||
package grpcurl_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/interop/grpc_testing"
|
||||
|
||||
. "github.com/fullstorydev/grpcurl"
|
||||
grpcurl_testing "github.com/fullstorydev/grpcurl/testing"
|
||||
grpcurl_testing "github.com/fullstorydev/grpcurl/internal/testing"
|
||||
)
|
||||
|
||||
func TestPlainText(t *testing.T) {
|
||||
|
|
@ -27,11 +26,11 @@ func TestPlainText(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBasicTLS(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "testing/tls/server.crt", "testing/tls/server.key", false)
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
|
@ -46,7 +45,7 @@ func TestBasicTLS(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInsecureClientTLS(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "testing/tls/server.crt", "testing/tls/server.key", false)
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
|
@ -65,11 +64,11 @@ func TestInsecureClientTLS(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestClientCertTLS(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", false)
|
||||
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "testing/tls/client.crt", "testing/tls/client.key")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "internal/testing/tls/client.crt", "internal/testing/tls/client.key")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
|
@ -84,11 +83,11 @@ func TestClientCertTLS(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRequireClientCertTLS(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", true)
|
||||
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", true)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "testing/tls/client.crt", "testing/tls/client.key")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "internal/testing/tls/client.crt", "internal/testing/tls/client.key")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
|
@ -103,7 +102,7 @@ func TestRequireClientCertTLS(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBrokenTLS_ClientPlainText(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "testing/tls/server.crt", "testing/tls/server.key", false)
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
|
@ -148,8 +147,8 @@ func TestBrokenTLS_ClientPlainText(t *testing.T) {
|
|||
|
||||
// but request fails because server closes connection upon seeing request
|
||||
// bytes that are not a TLS handshake
|
||||
cl := grpc_testing.NewTestServiceClient(e.cc)
|
||||
_, err = cl.UnaryCall(context.Background(), &grpc_testing.SimpleRequest{})
|
||||
cl := grpcurl_testing.NewTestServiceClient(e.cc)
|
||||
_, err = cl.UnaryCall(context.Background(), &grpcurl_testing.SimpleRequest{})
|
||||
if err == nil {
|
||||
t.Fatal("expecting failure")
|
||||
}
|
||||
|
|
@ -164,15 +163,15 @@ func TestBrokenTLS_ClientPlainText(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBrokenTLS_ServerPlainText(t *testing.T) {
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
||||
e, err := createTestServerAndClient(nil, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "first record does not look like a TLS handshake") {
|
||||
t.Fatalf("expecting TLS handshake failure, got: %v", err)
|
||||
|
|
@ -180,19 +179,19 @@ func TestBrokenTLS_ServerPlainText(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBrokenTLS_ServerUsesWrongCert(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "testing/tls/other.crt", "testing/tls/other.key", false)
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/other.crt", "internal/testing/tls/other.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "certificate is valid for") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
|
|
@ -200,39 +199,39 @@ func TestBrokenTLS_ServerUsesWrongCert(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBrokenTLS_ClientHasExpiredCert(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", false)
|
||||
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "testing/tls/expired.crt", "testing/tls/expired.key")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "internal/testing/tls/expired.crt", "internal/testing/tls/expired.key")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "bad certificate") {
|
||||
if !strings.Contains(err.Error(), "certificate") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBrokenTLS_ServerHasExpiredCert(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "testing/tls/expired.crt", "testing/tls/expired.key", false)
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/expired.crt", "internal/testing/tls/expired.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "certificate has expired or is not yet valid") {
|
||||
t.Fatalf("expecting TLS certificate expired, got: %v", err)
|
||||
|
|
@ -240,70 +239,78 @@ func TestBrokenTLS_ServerHasExpiredCert(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBrokenTLS_ClientNotTrusted(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", true)
|
||||
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", true)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "testing/tls/wrong-client.crt", "testing/tls/wrong-client.key")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "internal/testing/tls/wrong-client.crt", "internal/testing/tls/wrong-client.key")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "bad certificate") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
// Check for either the old error (Go <=1.24) or the new one (Go 1.25+)
|
||||
// Go 1.24: "bad certificate"
|
||||
// Go 1.25: "handshake failure"
|
||||
errMsg := err.Error()
|
||||
if !strings.Contains(errMsg, "bad certificate") && !strings.Contains(errMsg, "handshake failure") {
|
||||
t.Fatalf("expecting a specific TLS certificate or handshake error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBrokenTLS_ServerNotTrusted(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "testing/tls/server.crt", "testing/tls/server.key", false)
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "", "testing/tls/client.crt", "testing/tls/client.key")
|
||||
clientCreds, err := ClientTransportCredentials(false, "", "internal/testing/tls/client.crt", "internal/testing/tls/client.key")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "certificate signed by unknown authority") {
|
||||
if !strings.Contains(err.Error(), "certificate") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBrokenTLS_RequireClientCertButNonePresented(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", true)
|
||||
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", true)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "bad certificate") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
// Check for either the old error (Go <=1.24) or the new one (Go 1.25+)
|
||||
// Go 1.24: "bad certificate"
|
||||
// Go 1.25: "handshake failure"
|
||||
errMsg := err.Error()
|
||||
if !strings.Contains(errMsg, "bad certificate") && !strings.Contains(errMsg, "handshake failure") {
|
||||
t.Fatalf("expecting a specific TLS certificate or handshake error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func simpleTest(t *testing.T, cc *grpc.ClientConn) {
|
||||
cl := grpc_testing.NewTestServiceClient(cc)
|
||||
cl := grpcurl_testing.NewTestServiceClient(cc)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
_, err := cl.UnaryCall(ctx, &grpc_testing.SimpleRequest{}, grpc.WaitForReady(true))
|
||||
_, err := cl.UnaryCall(ctx, &grpcurl_testing.SimpleRequest{}, grpc.WaitForReady(true))
|
||||
if err != nil {
|
||||
t.Errorf("simple RPC failed: %v", err)
|
||||
}
|
||||
|
|
@ -323,7 +330,7 @@ func createTestServerAndClient(serverCreds, clientCreds credentials.TransportCre
|
|||
svrOpts = []grpc.ServerOption{grpc.Creds(serverCreds)}
|
||||
}
|
||||
svr := grpc.NewServer(svrOpts...)
|
||||
grpc_testing.RegisterTestServiceServer(svr, grpcurl_testing.TestServer{})
|
||||
grpcurl_testing.RegisterTestServiceServer(svr, grpcurl_testing.TestServer{})
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return e, err
|
||||
|
|
@ -350,7 +357,7 @@ type testEnv struct {
|
|||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func (e testEnv) Close() {
|
||||
func (e *testEnv) Close() {
|
||||
if e.cc != nil {
|
||||
e.cc.Close()
|
||||
e.cc = nil
|
||||
|
|
|
|||
Loading…
Reference in New Issue