Compare commits

..

No commits in common. "master" and "v1.8.6" have entirely different histories.

39 changed files with 1655 additions and 1876 deletions

View File

@ -4,37 +4,52 @@ shared_configs:
- run: - run:
name: Run tests name: Run tests
command: | command: |
make test make deps test
# Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference # Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1 version: 2.1
jobs: jobs:
build-1-23: build-1-15:
working_directory: ~/repo working_directory: ~/repo
docker: docker:
- image: cimg/go:1.23 - image: circleci/golang:1.15
steps: *simple_job_steps steps: *simple_job_steps
build-1-24: build-1-16:
working_directory: ~/repo working_directory: ~/repo
docker: docker:
- image: cimg/go:1.24 - image: circleci/golang:1.16
steps: *simple_job_steps
build-1-25:
working_directory: ~/repo
docker:
- image: cimg/go:1.25
steps: steps:
- checkout - checkout
- restore_cache:
keys:
- go-mod-v4-{{ checksum "go.sum" }}
- run: - run:
name: Run tests and linters name: Install Dependencies
command: go mod download
- save_cache:
key: go-mod-v4-{{ checksum "go.sum" }}
paths:
- "/go/pkg/mod"
- run:
name: Run tests
command: | command: |
#mkdir -p /tmp/test-reports
#gotestsum --junitfile /tmp/test-reports/unit-tests.xml
make ci make ci
#- store_test_results:
# path: /tmp/test-reports
build-1-17:
working_directory: ~/repo
docker:
- image: circleci/golang:1.17
steps: *simple_job_steps
workflows: workflows:
pr-build-test: pr-build-test:
jobs: jobs:
- build-1-23 - build-1-15
- build-1-24 - build-1-16
- build-1-25 - build-1-17

View File

@ -1,22 +0,0 @@
# 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 }}

2
.gitignore vendored
View File

@ -1,5 +1,3 @@
dist/ dist/
.idea/ .idea/
VERSION VERSION
.tmp/
*.snap

View File

@ -8,56 +8,28 @@ builds:
goarch: goarch:
- amd64 - amd64
- 386 - 386
- arm
- arm64 - arm64
- s390x - s390x
- ppc64le
goarm:
- 5
- 6
- 7
ignore: ignore:
- goos: darwin - goos: darwin
goarch: 386 goarch: 386
- goos: windows - goos: windows
goarch: arm64 goarch: arm64
- goos: darwin
goarch: arm
- goos: windows
goarch: arm
- goos: darwin - goos: darwin
goarch: s390x goarch: s390x
- goos: windows - goos: windows
goarch: s390x goarch: s390x
- goos: darwin
goarch: ppc64le
- goos: windows
goarch: ppc64le
ldflags: ldflags:
- -s -w -X main.version=v{{.Version}} - -s -w -X main.version=v{{.Version}}
archives: archives:
- format: tar.gz - 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: format_overrides:
- goos: windows - goos: windows
format: zip format: zip
replacements:
amd64: x86_64
386: x86_32
darwin: osx
files: files:
- LICENSE - 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

View File

@ -1,5 +1,5 @@
FROM golang:1.25-alpine AS builder FROM golang:1.15-alpine as builder
LABEL maintainer="Fullstory Engineering" MAINTAINER FullStory Engineering
# create non-privileged group and user # create non-privileged group and user
RUN addgroup -S grpcurl && adduser -S grpcurl -G grpcurl RUN addgroup -S grpcurl && adduser -S grpcurl -G grpcurl
@ -16,15 +16,6 @@ RUN go build -o /grpcurl \
-ldflags "-w -extldflags \"-static\" -X \"main.version=$(cat VERSION)\"" \ -ldflags "-w -extldflags \"-static\" -X \"main.version=$(cat VERSION)\"" \
./cmd/grpcurl ./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 # New FROM so we have a nice'n'tiny image
FROM scratch FROM scratch
WORKDIR / WORKDIR /

View File

@ -1,6 +1,6 @@
The MIT License (MIT) 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,29 +1,20 @@
dev_build_version=$(shell git describe --tags --always --dirty) 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 # 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 # 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 # 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* # 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. # to fix some of the things they consider to be violations.
.PHONY: ci .PHONY: ci
ci: deps checkgofmt checkgenerate vet staticcheck ineffassign predeclared test ci: deps checkgofmt vet staticcheck ineffassign predeclared test
.PHONY: deps .PHONY: deps
deps: deps:
go get -d -v -t ./... go get -d -v -t ./...
go mod tidy
.PHONY: updatedeps .PHONY: updatedeps
updatedeps: updatedeps:
go get -d -v -t -u -f ./... go get -d -v -t -u -f ./...
go mod tidy
.PHONY: install .PHONY: install
install: install:
@ -31,8 +22,8 @@ install:
.PHONY: release .PHONY: release
release: release:
@go install github.com/goreleaser/goreleaser@v1.21.0 @go install github.com/goreleaser/goreleaser@v0.134.0
goreleaser release --clean goreleaser --rm-dist
.PHONY: docker .PHONY: docker
docker: docker:
@ -40,22 +31,6 @@ docker:
docker build -t fullstorydev/grpcurl:$(dev_build_version) . docker build -t fullstorydev/grpcurl:$(dev_build_version) .
@rm 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 .PHONY: checkgofmt
checkgofmt: checkgofmt:
gofmt -s -l . gofmt -s -l .
@ -67,10 +42,12 @@ checkgofmt:
vet: vet:
go 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 .PHONY: staticcheck
staticcheck: staticcheck:
@go install honnef.co/go/tools/cmd/staticcheck@2025.1.1 @go install honnef.co/go/tools/cmd/staticcheck@v0.0.1-2020.1.4
staticcheck -checks "inherit,-SA1019" ./... staticcheck ./...
.PHONY: ineffassign .PHONY: ineffassign
ineffassign: ineffassign:
@ -79,25 +56,23 @@ ineffassign:
.PHONY: predeclared .PHONY: predeclared
predeclared: predeclared:
@go install github.com/nishanths/predeclared@51e8c974458a0f93dc03fe356f91ae1a6d791e6f @go install github.com/nishanths/predeclared@86fad755b4d3
predeclared ./... predeclared .
# Intentionally omitted from CI, but target here for ad-hoc reports. # Intentionally omitted from CI, but target here for ad-hoc reports.
.PHONY: golint .PHONY: golint
golint: golint:
@go install golang.org/x/lint/golint@v0.0.0-20210508222113-6edffad5e616 # TODO: pin version
@go install golang.org/x/lint/golint@latest
golint -min_confidence 0.9 -set_exit_status ./... golint -min_confidence 0.9 -set_exit_status ./...
# Intentionally omitted from CI, but target here for ad-hoc reports. # Intentionally omitted from CI, but target here for ad-hoc reports.
.PHONY: errcheck .PHONY: errcheck
errcheck: errcheck:
@go install github.com/kisielk/errcheck@v1.2.0 # TODO: pin version
@go install github.com/kisielk/errcheck@latest
errcheck ./... errcheck ./...
.PHONY: test .PHONY: test
test: deps test:
CGO_ENABLED=1 go test -race ./... go test -race ./...
.tmp/protoc/bin/protoc: ./Makefile ./download_protoc.sh
./download_protoc.sh

View File

@ -1,7 +1,6 @@
# gRPCurl # gRPCurl
[![Build Status](https://circleci.com/gh/fullstorydev/grpcurl/tree/master.svg?style=svg)](https://circleci.com/gh/fullstorydev/grpcurl/tree/master) [![Build Status](https://circleci.com/gh/fullstorydev/grpcurl/tree/master.svg?style=svg)](https://circleci.com/gh/fullstorydev/grpcurl/tree/master)
[![Go Report Card](https://goreportcard.com/badge/github.com/fullstorydev/grpcurl)](https://goreportcard.com/report/github.com/fullstorydev/grpcurl) [![Go Report Card](https://goreportcard.com/badge/github.com/fullstorydev/grpcurl)](https://goreportcard.com/report/github.com/fullstorydev/grpcurl)
[![Snap Release Status](https://snapcraft.io/grpcurl/badge.svg)](https://snapcraft.io/grpcurl)
`grpcurl` is a command-line tool that lets you interact with gRPC servers. It's `grpcurl` is a command-line tool that lets you interact with gRPC servers. It's
basically `curl` for gRPC servers. basically `curl` for gRPC servers.
@ -15,7 +14,7 @@ This program accepts messages using JSON encoding, which is much more friendly f
humans and scripts. humans and scripts.
With this tool you can also browse the schema for gRPC services, either by querying 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/v1/reflection.proto), a server that supports [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto),
by reading proto source files, or by loading in compiled "protoset" files (files that contain 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)). 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 In fact, the way the tool transforms JSON request data into a binary encoded protobuf
@ -80,12 +79,6 @@ 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_: You can see more details and the full list of other packages for `grpcurl` at _repology.org_:
https://repology.org/project/grpcurl/information https://repology.org/project/grpcurl/information
### Snap
You can install `grpcurl` using the snap package:
`snap install grpcurl`
### From Source ### From Source
If you already have the [Go SDK](https://golang.org/doc/install) installed, you can use the `go` If you already have the [Go SDK](https://golang.org/doc/install) installed, you can use the `go`
tool to install `grpcurl`: tool to install `grpcurl`:
@ -152,13 +145,6 @@ grpcurl -d @ grpc.server.com:443 my.custom.server.Service/Method <<EOM
} }
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 ### Listing Services
To list all services exposed by a server, use the "list" verb. When using `.proto` source To list all services exposed by a server, use the "list" verb. When using `.proto` source
@ -173,13 +159,6 @@ grpcurl -protoset my-protos.bin list
# Using proto sources # Using proto sources
grpcurl -import-path ../protos -proto my-stuff.proto list 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: The "list" verb also lets you see all methods in a particular service:
@ -213,7 +192,7 @@ are needed to use them.
### Server Reflection ### 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/v1/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/v1alpha/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). 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).

9
cmd/grpcurl/go1_10.go Normal file
View File

@ -0,0 +1,9 @@
// +build go1.10
package main
func indent() string {
// In Go 1.10 and up, the flag package automatically
// adds the right indentation.
return ""
}

9
cmd/grpcurl/go1_9.go Normal file
View File

@ -0,0 +1,9 @@
// +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"
}

View File

@ -8,21 +8,20 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"math"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 required to use APIs in other grpcurl package "github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/grpcreflect" "github.com/jhump/protoreflect/grpcreflect"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/alts"
"google.golang.org/grpc/keepalive" "google.golang.org/grpc/keepalive"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/descriptorpb"
@ -34,14 +33,14 @@ import (
"github.com/fullstorydev/grpcurl" "github.com/fullstorydev/grpcurl"
) )
// To avoid confusion between program error codes and the gRPC response // To avoid confusion between program error codes and the gRPC resonse
// status codes 'Cancelled' and 'Unknown', 1 and 2 respectively, // status codes 'Cancelled' and 'Unknown', 1 and 2 respectively,
// the response status codes emitted use an offset of 64 // the response status codes emitted use an offest of 64
const statusCodeOffset = 64 const statusCodeOffset = 64
const noVersion = "dev build <no version set>" const no_version = "dev build <no version set>"
var version = noVersion var version = no_version
var ( var (
exit = os.Exit exit = os.Exit
@ -54,14 +53,11 @@ var (
Print usage instructions and exit.`)) Print usage instructions and exit.`))
printVersion = flags.Bool("version", false, prettify(` printVersion = flags.Bool("version", false, prettify(`
Print version.`)) Print version.`))
plaintext = flags.Bool("plaintext", false, prettify(` plaintext = flags.Bool("plaintext", false, prettify(`
Use plain-text HTTP/2 when connecting to server (no TLS).`)) Use plain-text HTTP/2 when connecting to server (no TLS).`))
insecure = flags.Bool("insecure", false, prettify(` insecure = flags.Bool("insecure", false, prettify(`
Skip server certificate and domain verification. (NOT SECURE!) Not Skip server certificate and domain verification. (NOT SECURE!) Not
valid with -plaintext option.`)) valid with -plaintext option.`))
// TLS Options
cacert = flags.String("cacert", "", prettify(` cacert = flags.String("cacert", "", prettify(`
File containing trusted root certificates for verifying the server. File containing trusted root certificates for verifying the server.
Ignored if -insecure is specified.`)) Ignored if -insecure is specified.`))
@ -71,13 +67,6 @@ var (
key = flags.String("key", "", prettify(` key = flags.String("key", "", prettify(`
File containing client private key, to present to the server. Not valid File containing client private key, to present to the server. Not valid
with -plaintext option. Must also provide -cert option.`)) 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 protoset multiString
protoFiles multiString protoFiles multiString
importPaths multiString importPaths multiString
@ -98,8 +87,7 @@ var (
value of the ":authority" pseudo-header in the HTTP/2 protocol. When TLS 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 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 server's certificate. It defaults to the address that is provided in the
positional arguments, or 'localhost' in the case of a unix domain positional arguments.`))
socket.`))
userAgent = flags.String("user-agent", "", prettify(` userAgent = flags.String("user-agent", "", prettify(`
If set, the specified value will be added to the User-Agent header set If set, the specified value will be added to the User-Agent header set
by the grpc-go library. by the grpc-go library.
@ -121,7 +109,7 @@ var (
separator.`)) separator.`))
allowUnknownFields = flags.Bool("allow-unknown-fields", false, prettify(` allowUnknownFields = flags.Bool("allow-unknown-fields", false, prettify(`
When true, the request contents, if 'json' format is used, allows When true, the request contents, if 'json' format is used, allows
unknown fields to be present. They will be ignored when parsing unkown fields to be present. They will be ignored when parsing
the request.`)) the request.`))
connectTimeout = flags.Float64("connect-timeout", 0, prettify(` connectTimeout = flags.Float64("connect-timeout", 0, prettify(`
The maximum time, in seconds, to wait for connection to be established. The maximum time, in seconds, to wait for connection to be established.
@ -135,11 +123,9 @@ var (
is received for this same period then the connection is closed and the is received for this same period then the connection is closed and the
operation fails.`)) operation fails.`))
maxTime = flags.Float64("max-time", 0, prettify(` maxTime = flags.Float64("max-time", 0, prettify(`
The maximum total time the operation can take, in seconds. This sets a The maximum total time the operation can take, in seconds. This is
timeout on the gRPC context, allowing both client and server to give up useful for preventing batch jobs that use grpcurl from hanging due to
after the deadline has past. This is useful for preventing batch jobs slow or bad network links or due to incorrect stream method usage.`))
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(` maxMsgSz = flags.Int("max-msg-sz", 0, prettify(`
The maximum encoded size of a response message, in bytes, that grpcurl The maximum encoded size of a response message, in bytes, that grpcurl
will accept. If not specified, defaults to 4,194,304 (4 megabytes).`)) will accept. If not specified, defaults to 4,194,304 (4 megabytes).`))
@ -152,20 +138,12 @@ var (
file if this option is given. When invoking an RPC and this option is 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 given, the method being invoked and its transitive dependencies will be
included in the output file.`)) 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(` msgTemplate = flags.Bool("msg-template", false, prettify(`
When describing messages, show a template of input data.`)) When describing messages, show a template of input data.`))
verbose = flags.Bool("v", false, prettify(` verbose = flags.Bool("v", false, prettify(`
Enable verbose output.`)) Enable verbose output.`))
veryVerbose = flags.Bool("vv", false, prettify(` veryVerbose = flags.Bool("vv", false, prettify(`
Enable very verbose output (includes timing data).`)) Enable very verbose output.`))
serverName = flags.String("servername", "", prettify(` serverName = flags.String("servername", "", prettify(`
Override server name when validating TLS certificate. This flag is Override server name when validating TLS certificate. This flag is
ignored if -plaintext or -insecure is used. ignored if -plaintext or -insecure is used.
@ -222,14 +200,6 @@ func init() {
-use-reflection is used in combination with a -proto or -protoset flag, -use-reflection is used in combination with a -proto or -protoset flag,
the provided descriptor sources will be used in addition to server the provided descriptor sources will be used in addition to server
reflection to resolve messages and extensions.`)) 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 type multiString []string
@ -286,32 +256,6 @@ func (cs compositeSource) AllExtensionsForType(typeName string) ([]*desc.FieldDe
return exts, nil 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() { func main() {
flags.Usage = usage flags.Usage = usage
flags.Parse(os.Args[1:]) flags.Parse(os.Args[1:])
@ -324,9 +268,6 @@ func main() {
os.Exit(0) 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. // Do extra validation on arguments and figure out what user asked us to do.
if *connectTimeout < 0 { if *connectTimeout < 0 {
fail(nil, "The -connect-timeout argument must not be negative.") fail(nil, "The -connect-timeout argument must not be negative.")
@ -340,27 +281,18 @@ func main() {
if *maxMsgSz < 0 { if *maxMsgSz < 0 {
fail(nil, "The -max-msg-sz argument must not be negative.") fail(nil, "The -max-msg-sz argument must not be negative.")
} }
if *plaintext && *usealts { if *plaintext && *insecure {
fail(nil, "The -plaintext and -alts arguments are mutually exclusive.") fail(nil, "The -plaintext and -insecure arguments are mutually exclusive.")
} }
if *insecure && !usetls { if *plaintext && *cert != "" {
fail(nil, "The -insecure argument can only be used with TLS.") fail(nil, "The -plaintext and -cert arguments are mutually exclusive.")
} }
if *cert != "" && !usetls { if *plaintext && *key != "" {
fail(nil, "The -cert argument can only be used with TLS.") fail(nil, "The -plaintext and -key arguments are mutually exclusive.")
}
if *key != "" && !usetls {
fail(nil, "The -key argument can only be used with TLS.")
} }
if (*key == "") != (*cert == "") { if (*key == "") != (*cert == "") {
fail(nil, "The -cert and -key arguments must be used together and both be present.") 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" { if *format != "json" && *format != "text" {
fail(nil, "The -format option must be 'json' or 'text'.") fail(nil, "The -format option must be 'json' or 'text'.")
} }
@ -397,16 +329,8 @@ func main() {
if *verbose { if *verbose {
verbosityLevel = 1 verbosityLevel = 1
} }
var rootTiming *timingData
if *veryVerbose { if *veryVerbose {
verbosityLevel = 2 verbosityLevel = 2
rootTiming = &timingData{Title: "Timing Data", Start: time.Now()}
defer func() {
rootTiming.Done()
dumpTiming(rootTiming, 0)
}()
} }
var symbol string var symbol string
@ -458,24 +382,22 @@ func main() {
ctx := context.Background() ctx := context.Background()
if *maxTime > 0 { if *maxTime > 0 {
timeout := floatSecondsToDuration(*maxTime) timeout := time.Duration(*maxTime * float64(time.Second))
var cancel context.CancelFunc var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout) ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel() defer cancel()
} }
dial := func() *grpc.ClientConn { dial := func() *grpc.ClientConn {
dialTiming := rootTiming.Child("Dial")
defer dialTiming.Done()
dialTime := 10 * time.Second dialTime := 10 * time.Second
if *connectTimeout > 0 { if *connectTimeout > 0 {
dialTime = floatSecondsToDuration(*connectTimeout) dialTime = time.Duration(*connectTimeout * float64(time.Second))
} }
ctx, cancel := context.WithTimeout(ctx, dialTime) ctx, cancel := context.WithTimeout(ctx, dialTime)
defer cancel() defer cancel()
var opts []grpc.DialOption var opts []grpc.DialOption
if *keepaliveTime > 0 { if *keepaliveTime > 0 {
timeout := floatSecondsToDuration(*keepaliveTime) timeout := time.Duration(*keepaliveTime * float64(time.Second))
opts = append(opts, grpc.WithKeepaliveParams(keepalive.ClientParameters{ opts = append(opts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: timeout, Time: timeout,
Timeout: timeout, Timeout: timeout,
@ -484,31 +406,8 @@ func main() {
if *maxMsgSz > 0 { if *maxMsgSz > 0 {
opts = append(opts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(*maxMsgSz))) 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 var creds credentials.TransportCredentials
if *plaintext { 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) tlsConf, err := grpcurl.ClientTLSConfig(*insecure, *cacert, *cert, *key)
if err != nil { if err != nil {
fail(err, "Failed to create TLS config") fail(err, "Failed to create TLS config")
@ -541,13 +440,12 @@ func main() {
if overrideName != "" { if overrideName != "" {
opts = append(opts, grpc.WithAuthority(overrideName)) opts = append(opts, grpc.WithAuthority(overrideName))
} }
tlsTiming.Done() } else if *authority != "" {
} else { opts = append(opts, grpc.WithAuthority(*authority))
panic("Should have defaulted to use TLS.")
} }
grpcurlUA := "grpcurl/" + version grpcurlUA := "grpcurl/" + version
if version == noVersion { if version == no_version {
grpcurlUA = "grpcurl/dev-build (no version set)" grpcurlUA = "grpcurl/dev-build (no version set)"
} }
if *userAgent != "" { if *userAgent != "" {
@ -555,9 +453,11 @@ func main() {
} }
opts = append(opts, grpc.WithUserAgent(grpcurlUA)) opts = append(opts, grpc.WithUserAgent(grpcurlUA))
blockingDialTiming := dialTiming.Child("BlockingDial") network := "tcp"
defer blockingDialTiming.Done() if isUnixSocket != nil && isUnixSocket() {
cc, err := grpcurl.BlockingDial(ctx, "", target, creds, opts...) network = "unix"
}
cc, err := grpcurl.BlockingDial(ctx, network, target, creds, opts...)
if err != nil { if err != nil {
fail(err, "Failed to dial target host %q", target) fail(err, "Failed to dial target host %q", target)
} }
@ -608,8 +508,7 @@ func main() {
md := grpcurl.MetadataFromHeaders(append(addlHeaders, reflHeaders...)) md := grpcurl.MetadataFromHeaders(append(addlHeaders, reflHeaders...))
refCtx := metadata.NewOutgoingContext(ctx, md) refCtx := metadata.NewOutgoingContext(ctx, md)
cc = dial() cc = dial()
refClient = grpcreflect.NewClientAuto(refCtx, cc) refClient = grpcreflect.NewClient(refCtx, reflectpb.NewServerReflectionClient(cc))
refClient.AllowMissingFileDescriptors()
reflSource := grpcurl.DescriptorSourceFromServer(ctx, refClient) reflSource := grpcurl.DescriptorSourceFromServer(ctx, refClient)
if fileSource != nil { if fileSource != nil {
descSource = compositeSource{reflSource, fileSource} descSource = compositeSource{reflSource, fileSource}
@ -654,9 +553,6 @@ func main() {
if err := writeProtoset(descSource, svcs...); err != nil { if err := writeProtoset(descSource, svcs...); err != nil {
fail(err, "Failed to write protoset to %s", *protosetOut) 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 { } else {
methods, err := grpcurl.ListMethods(descSource, symbol) methods, err := grpcurl.ListMethods(descSource, symbol)
if err != nil { if err != nil {
@ -672,9 +568,6 @@ func main() {
if err := writeProtoset(descSource, symbol); err != nil { if err := writeProtoset(descSource, symbol); err != nil {
fail(err, "Failed to write protoset to %s", *protosetOut) 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 { } else if describe {
@ -779,9 +672,6 @@ func main() {
if err := writeProtoset(descSource, symbols...); err != nil { if err := writeProtoset(descSource, symbols...); err != nil {
fail(err, "Failed to write protoset to %s", *protosetOut) 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 { } else {
// Invoke an RPC // Invoke an RPC
@ -814,9 +704,7 @@ func main() {
VerbosityLevel: verbosityLevel, VerbosityLevel: verbosityLevel,
} }
invokeTiming := rootTiming.Child("InvokeRPC")
err = grpcurl.InvokeRPC(ctx, descSource, cc, symbol, append(addlHeaders, rpcHeaders...), h, rf.Next) err = grpcurl.InvokeRPC(ctx, descSource, cc, symbol, append(addlHeaders, rpcHeaders...), h, rf.Next)
invokeTiming.Done()
if err != nil { if err != nil {
if errStatus, ok := status.FromError(err); ok && *formatError { if errStatus, ok := status.FromError(err); ok && *formatError {
h.Status = errStatus h.Status = errStatus
@ -847,17 +735,6 @@ 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() { func usage() {
fmt.Fprintf(os.Stderr, `Usage: fmt.Fprintf(os.Stderr, `Usage:
%s [flags] [address] [list|describe] [symbol] %s [flags] [address] [list|describe] [symbol]
@ -905,7 +782,7 @@ func prettify(docString string) string {
j++ j++
} }
return strings.Join(parts[:j], "\n") return strings.Join(parts[:j], "\n"+indent())
} }
func warn(msg string, args ...interface{}) { func warn(msg string, args ...interface{}) {
@ -941,13 +818,6 @@ func writeProtoset(descSource grpcurl.DescriptorSource, symbols ...string) error
return grpcurl.WriteProtoset(f, descSource, symbols...) 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 { type optionalBoolFlag struct {
set, val bool set, val bool
} }
@ -972,12 +842,3 @@ func (f *optionalBoolFlag) Set(s string) error {
func (f *optionalBoolFlag) IsBoolFlag() bool { func (f *optionalBoolFlag) IsBoolFlag() bool {
return true 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)
}

View File

@ -1,5 +1,4 @@
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows // +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package main package main

View File

@ -5,15 +5,13 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"os" "io/ioutil"
"path/filepath"
"sync" "sync"
"github.com/golang/protobuf/proto" //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 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/desc/protoparse" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/desc/protoparse"
"github.com/jhump/protoreflect/desc/protoprint" "github.com/jhump/protoreflect/dynamic"
"github.com/jhump/protoreflect/dynamic" //lint:ignore SA1019 same as above
"github.com/jhump/protoreflect/grpcreflect" "github.com/jhump/protoreflect/grpcreflect"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
@ -43,7 +41,7 @@ type DescriptorSource interface {
func DescriptorSourceFromProtoSets(fileNames ...string) (DescriptorSource, error) { func DescriptorSourceFromProtoSets(fileNames ...string) (DescriptorSource, error) {
files := &descriptorpb.FileDescriptorSet{} files := &descriptorpb.FileDescriptorSet{}
for _, fileName := range fileNames { for _, fileName := range fileNames {
b, err := os.ReadFile(fileName) b, err := ioutil.ReadFile(fileName)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not load protoset file %q: %v", fileName, err) return nil, fmt.Errorf("could not load protoset file %q: %v", fileName, err)
} }
@ -260,9 +258,19 @@ func reflectionSupport(err error) error {
// given output. The output will include descriptors for all files in which the // given output. The output will include descriptors for all files in which the
// symbols are defined as well as their transitive dependencies. // symbols are defined as well as their transitive dependencies.
func WriteProtoset(out io.Writer, descSource DescriptorSource, symbols ...string) error { func WriteProtoset(out io.Writer, descSource DescriptorSource, symbols ...string) error {
filenames, fds, err := getFileDescriptors(symbols, descSource) // 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 { if err != nil {
return err 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())
}
} }
// now expand that to include transitive dependencies in topologically sorted // now expand that to include transitive dependencies in topologically sorted
// order (such that file always appears after its dependencies) // order (such that file always appears after its dependencies)
@ -294,76 +302,3 @@ func addFilesToSet(allFiles []*descriptorpb.FileDescriptorProto, expanded map[st
} }
return append(allFiles, fd.AsFileDescriptorProto()) 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)
}

View File

@ -2,7 +2,7 @@ package grpcurl
import ( import (
"bytes" "bytes"
"os" "io/ioutil"
"testing" "testing"
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API "github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
@ -34,7 +34,7 @@ func TestWriteProtoset(t *testing.T) {
} }
func loadProtoset(path string) (*descriptorpb.FileDescriptorSet, error) { func loadProtoset(path string) (*descriptorpb.FileDescriptorSet, error) {
b, err := os.ReadFile(path) b, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,35 +0,0 @@
#!/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

View File

@ -11,10 +11,10 @@ import (
"strings" "strings"
"sync" "sync"
"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/jsonpb" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/golang/protobuf/proto" //lint:ignore SA1019 same as above "github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/dynamic" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/dynamic"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
@ -136,25 +136,10 @@ type Formatter func(proto.Message) (string, error)
func NewJSONFormatter(emitDefaults bool, resolver jsonpb.AnyResolver) Formatter { func NewJSONFormatter(emitDefaults bool, resolver jsonpb.AnyResolver) Formatter {
marshaler := jsonpb.Marshaler{ marshaler := jsonpb.Marshaler{
EmitDefaults: emitDefaults, EmitDefaults: emitDefaults,
Indent: " ",
AnyResolver: resolver, AnyResolver: resolver,
} }
// Workaround for indentation issue in jsonpb with Any messages. return marshaler.MarshalToString
// 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 // NewTextFormatter returns a formatter that returns strings in the protobuf
@ -212,20 +197,10 @@ func (tf *textFormatter) format(m proto.Message) (string, error) {
return str, nil return str, nil
} }
// Format of request data. The allowed values are 'json' or 'text'.
type Format string type Format string
const ( 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") 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") FormatText = Format("text")
) )
@ -289,11 +264,11 @@ func (r *anyResolver) Resolve(typeUrl string) (proto.Message, error) {
if !ok { if !ok {
return nil, fmt.Errorf("unknown message: %s", typeUrl) return nil, fmt.Errorf("unknown message: %s", typeUrl)
} }
// populate any extensions for this message, too (if there are any) // populate any extensions for this message, too
if exts, err := r.source.AllExtensionsForType(mname); err == nil { if exts, err := r.source.AllExtensionsForType(mname); err != nil {
if err := r.er.AddExtension(exts...); err != nil { return nil, err
} else if err := r.er.AddExtension(exts...); err != nil {
return nil, err return nil, err
}
} }
if r.mf == nil { if r.mf == nil {
@ -453,7 +428,7 @@ type DefaultEventHandler struct {
// the given output. If verbose is true, all events are logged. Otherwise, only // the given output. If verbose is true, all events are logged. Otherwise, only
// response messages are logged. // response messages are logged.
// //
// Deprecated: NewDefaultEventHandler exists for compatibility. // Deprecated: NewDefaultEventHandler exists for compatability.
// It doesn't allow fine control over the `VerbosityLevel` // It doesn't allow fine control over the `VerbosityLevel`
// and provides only 0 and 1 options (which corresponds to the `verbose` argument). // and provides only 0 and 1 options (which corresponds to the `verbose` argument).
// Use DefaultEventHandler{} initializer directly. // Use DefaultEventHandler{} initializer directly.

View File

@ -7,9 +7,9 @@ import (
"strings" "strings"
"testing" "testing"
"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/jsonpb" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/golang/protobuf/proto" //lint:ignore SA1019 same as above "github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/desc"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
) )

36
go.mod
View File

@ -1,32 +1,14 @@
module github.com/fullstorydev/grpcurl module github.com/fullstorydev/grpcurl
go 1.24.0 go 1.15
toolchain go1.24.1
require ( require (
github.com/golang/protobuf v1.5.4 cloud.google.com/go v0.56.0 // indirect
github.com/jhump/protoreflect v1.18.0 github.com/davecgh/go-spew v1.1.1 // indirect
google.golang.org/grpc v1.66.2 github.com/golang/protobuf v1.5.2
google.golang.org/protobuf v1.36.11 github.com/jhump/protoreflect v1.10.3
) golang.org/x/text v0.3.7 // indirect
google.golang.org/grpc v1.44.0
require ( google.golang.org/protobuf v1.26.0
cel.dev/expr v0.15.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // 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
) )

402
go.sum
View File

@ -1,56 +1,354 @@
cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4=
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
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/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021 h1:fP+fF0up6oPY49OrjPrhIJ8yQfdIM85NXMLkMg1EXVs=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/jhump/protoreflect v1.18.0 h1:TOz0MSR/0JOZ5kECB/0ufGnC2jdsgZ123Rd/k4Z5/2w= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/jhump/protoreflect v1.18.0/go.mod h1:ezWcltJIVF4zYdIFM+D/sHV4Oh5LNU08ORzCGfwvTz8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/jhump/protoreflect/v2 v2.0.0-beta.1 h1:Dw1rslK/VotaUGYsv53XVWITr+5RCPXfvvlGrM/+B6w= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/jhump/protoreflect/v2 v2.0.0-beta.1/go.mod h1:D9LBEowZyv8/iSu97FU2zmXG3JxVTmNw21mu63niFzU= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 h1:KPpdlQLZcHfTMQRi6bFQ7ogNO0ltFT4PmtwTLW4W+14= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= 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/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
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/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
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/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/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+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/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
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/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jhump/protoreflect v1.10.3 h1:8ogeubpKh2TiulA0apmGlW5YAH4U1Vi4TINIP+gpNfQ=
github.com/jhump/protoreflect v1.10.3/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
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/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.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-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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/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-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20190215142949-d0b11bdaac8a/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/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-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
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/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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-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-20190621195816-6e04913cbbac/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-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/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-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
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/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
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-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-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
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.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.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -14,22 +14,20 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"net" "net"
"os" "os"
"regexp" "regexp"
"slices"
"sort" "sort"
"strings" "strings"
"github.com/golang/protobuf/proto" //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 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/desc/protoprint" "github.com/jhump/protoreflect/desc/protoprint"
"github.com/jhump/protoreflect/dynamic" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/dynamic"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure" "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/metadata"
protov2 "google.golang.org/protobuf/proto" protov2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/descriptorpb"
@ -331,7 +329,7 @@ func fetchAllExtensions(source DescriptorSource, ext *dynamic.ExtensionRegistry,
return nil return nil
} }
// fullyConvertToDynamic attempts to convert the given message to a dynamic message as well // fullConvertToDynamic 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 // 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 // extensions registered that were not known when the given message was parsed, this effectively
// allows re-parsing to identify those extensions. // allows re-parsing to identify those extensions.
@ -409,9 +407,9 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
case "google.protobuf.Any": case "google.protobuf.Any":
// empty type URL is not allowed by JSON representation // empty type URL is not allowed by JSON representation
// so we must give it a dummy type // so we must give it a dummy type
var anyVal anypb.Any var any anypb.Any
_ = anypb.MarshalFrom(&anyVal, &emptypb.Empty{}, protov2.MarshalOptions{}) _ = anypb.MarshalFrom(&any, &emptypb.Empty{}, protov2.MarshalOptions{})
return &anyVal return &any
case "google.protobuf.Value": case "google.protobuf.Value":
// unset kind is not allowed by JSON representation // unset kind is not allowed by JSON representation
// so we must give it something // so we must give it something
@ -451,10 +449,12 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
dm := dynamic.NewMessage(md) dm := dynamic.NewMessage(md)
// if the message is a recursive structure, we don't want to blow the stack // if the message is a recursive structure, we don't want to blow the stack
if slices.Contains(path, md) { for _, seen := range path {
if seen == md {
// already visited this type; avoid infinite recursion // already visited this type; avoid infinite recursion
return dm return dm
} }
}
path = append(path, dm.GetMessageDescriptor()) path = append(path, dm.GetMessageDescriptor())
// for repeated fields, add a single element with default value // for repeated fields, add a single element with default value
@ -544,7 +544,7 @@ func ClientTLSConfig(insecureSkipVerify bool, cacertFile, clientCertFile, client
} else if cacertFile != "" { } else if cacertFile != "" {
// Create a certificate pool from the certificate authority // Create a certificate pool from the certificate authority
certPool := x509.NewCertPool() certPool := x509.NewCertPool()
ca, err := os.ReadFile(cacertFile) ca, err := ioutil.ReadFile(cacertFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read ca certificate: %v", err) return nil, fmt.Errorf("could not read ca certificate: %v", err)
} }
@ -581,7 +581,7 @@ func ServerTransportCredentials(cacertFile, serverCertFile, serverKeyFile string
if cacertFile != "" { if cacertFile != "" {
// Create a certificate pool from the certificate authority // Create a certificate pool from the certificate authority
certPool := x509.NewCertPool() certPool := x509.NewCertPool()
ca, err := os.ReadFile(cacertFile) ca, err := ioutil.ReadFile(cacertFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read ca certificate: %v", err) return nil, fmt.Errorf("could not read ca certificate: %v", err)
} }
@ -608,24 +608,7 @@ func ServerTransportCredentials(cacertFile, serverCertFile, serverKeyFile string
// BlockingDial is a helper method to dial the given address, using optional TLS credentials, // 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 // and blocking until the returned connection is ready. If the given credentials are nil, the
// connection will be insecure (plain-text). // 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) { 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 // 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 // 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. // custom dialer that can provide that info. That means we manage the TLS handshake.
@ -641,38 +624,26 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
// custom credentials and dialer will notify on error via the // custom credentials and dialer will notify on error via the
// writeResult function // writeResult function
if creds != nil {
creds = &errSignalingCreds{ creds = &errSignalingCreds{
TransportCredentials: creds, TransportCredentials: creds,
writeResult: writeResult, writeResult: writeResult,
} }
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)
} }
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) { 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 insecure.NewCredentials() dial transport
// 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) conn, err := (&net.Dialer{}).DialContext(ctx, network, address)
if err != nil { if err != nil {
// capture the error so we can provide a better message
writeResult(err) writeResult(err)
} }
return conn, err return conn, err
} }
opts = append([]grpc.DialOption{grpc.WithContextDialer(dialer)}, opts...)
}
// Even with grpc.FailOnNonTempDialError, this call will usually timeout in // Even with grpc.FailOnNonTempDialError, this call will usually timeout in
// the face of TLS handshake errors. So we can't rely on grpc.WithBlock() to // the face of TLS handshake errors. So we can't rely on grpc.WithBlock() to
@ -684,8 +655,13 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
opts = append([]grpc.DialOption{grpc.FailOnNonTempDialError(true)}, opts...) opts = append([]grpc.DialOption{grpc.FailOnNonTempDialError(true)}, opts...)
// But we don't want caller to be able to override these two, so we put // But we don't want caller to be able to override these two, so we put
// them *after* the explicitly provided options. // them *after* the explicitly provided options.
opts = append(opts, grpc.WithBlock(), grpc.WithTransportCredentials(creds)) opts = append(opts, grpc.WithBlock(), grpc.WithContextDialer(dialer))
if creds == nil {
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
} else {
opts = append(opts, grpc.WithTransportCredentials(creds))
}
conn, err := grpc.DialContext(ctx, address, opts...) conn, err := grpc.DialContext(ctx, address, opts...)
var res interface{} var res interface{}
if err != nil { if err != nil {

View File

@ -12,15 +12,16 @@ import (
"testing" "testing"
"time" "time"
"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/jsonpb" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/golang/protobuf/proto" //lint:ignore SA1019 same as above "github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/grpcreflect" "github.com/jhump/protoreflect/grpcreflect"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/reflection" "google.golang.org/grpc/reflection"
reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
. "github.com/fullstorydev/grpcurl" . "github.com/fullstorydev/grpcurl"
@ -81,7 +82,7 @@ func TestMain(m *testing.M) {
panic(err) panic(err)
} }
defer ccReflect.Close() defer ccReflect.Close()
refClient := grpcreflect.NewClientAuto(context.Background(), ccReflect) refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(ccReflect))
defer refClient.Reset() defer refClient.Reset()
sourceReflect = DescriptorSourceFromServer(context.Background(), refClient) sourceReflect = DescriptorSourceFromServer(context.Background(), refClient)
@ -117,7 +118,7 @@ func TestMain(m *testing.M) {
} }
func TestServerDoesNotSupportReflection(t *testing.T) { func TestServerDoesNotSupportReflection(t *testing.T) {
refClient := grpcreflect.NewClientAuto(context.Background(), ccNoReflect) refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(ccNoReflect))
defer refClient.Reset() defer refClient.Reset()
refSource := DescriptorSourceFromServer(context.Background(), refClient) refSource := DescriptorSourceFromServer(context.Background(), refClient)
@ -177,7 +178,7 @@ func doTestListServices(t *testing.T, source DescriptorSource, includeReflection
var expected []string var expected []string
if includeReflection { if includeReflection {
// when using server reflection, we see the TestService as well as the ServerReflection service // when using server reflection, we see the TestService as well as the ServerReflection service
expected = []string{"grpc.reflection.v1.ServerReflection", "grpc.reflection.v1alpha.ServerReflection", "testing.TestService"} expected = []string{"grpc.reflection.v1alpha.ServerReflection", "testing.TestService"}
} else { } else {
// without reflection, we see all services defined in the same test.proto file, which is the // without reflection, we see all services defined in the same test.proto file, which is the
// TestService as well as UnimplementedService // TestService as well as UnimplementedService
@ -215,11 +216,11 @@ func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection
if includeReflection { if includeReflection {
// when using server reflection, we see the TestService as well as the ServerReflection service // when using server reflection, we see the TestService as well as the ServerReflection service
names, err = ListMethods(source, "grpc.reflection.v1.ServerReflection") names, err = ListMethods(source, "grpc.reflection.v1alpha.ServerReflection")
if err != nil { if err != nil {
t.Fatalf("failed to list methods for ServerReflection: %v", err) t.Fatalf("failed to list methods for ServerReflection: %v", err)
} }
expected = []string{"grpc.reflection.v1.ServerReflection.ServerReflectionInfo"} expected = []string{"grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo"}
} else { } else {
// without reflection, we see all services defined in the same test.proto file, which is the // without reflection, we see all services defined in the same test.proto file, which is the
// TestService as well as UnimplementedService // TestService as well as UnimplementedService
@ -242,8 +243,12 @@ func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection
func TestGetAllFiles(t *testing.T) { func TestGetAllFiles(t *testing.T) {
expectedFiles := []string{"test.proto"} expectedFiles := []string{"test.proto"}
expectedFilesWithReflection := []string{ // server reflection picks up filename from linked in Go package,
"grpc/reflection/v1/reflection.proto", "grpc/reflection/v1alpha/reflection.proto", "test.proto", // which indicates "grpc_testing/test.proto", not our local copy.
expectedFilesWithReflection := [][]string{
{"grpc_reflection_v1alpha/reflection.proto", "test.proto"},
// depending on the version of grpc, the filenames could be prefixed with "interop/" and "reflection/"
{"reflection/grpc_reflection_v1alpha/reflection.proto", "test.proto"},
} }
for _, ds := range descSources { for _, ds := range descSources {
@ -256,11 +261,17 @@ func TestGetAllFiles(t *testing.T) {
match := false match := false
var expected []string var expected []string
if ds.includeRefl { if ds.includeRefl {
expected = expectedFilesWithReflection for _, expectedNames := range expectedFilesWithReflection {
expected = expectedNames
if reflect.DeepEqual(expected, names) {
match = true
break
}
}
} else { } else {
expected = expectedFiles expected = expectedFiles
}
match = reflect.DeepEqual(expected, names) match = reflect.DeepEqual(expected, names)
}
if !match { if !match {
t.Errorf("GetAllFiles returned wrong results: wanted %v, got %v", expected, names) t.Errorf("GetAllFiles returned wrong results: wanted %v, got %v", expected, names)
} }

View File

@ -12,7 +12,6 @@ import (
// bankServer implements the Bank gRPC service. // bankServer implements the Bank gRPC service.
type bankServer struct { type bankServer struct {
UnimplementedBankServer
allAccounts *accounts allAccounts *accounts
} }

View File

@ -1,13 +1,17 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.25.0-devel // protoc-gen-go v1.25.0-devel
// protoc v4.22.0 // protoc v3.14.0
// source: bank.proto // source: bank.proto
package main package main
import ( import (
context "context"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb" emptypb "google.golang.org/protobuf/types/known/emptypb"
@ -692,12 +696,10 @@ type TransferRequest struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Types that are assignable to Source: // Types that are assignable to Source:
//
// *TransferRequest_SourceAccountNumber // *TransferRequest_SourceAccountNumber
// *TransferRequest_ExternalSource // *TransferRequest_ExternalSource
Source isTransferRequest_Source `protobuf_oneof:"source"` Source isTransferRequest_Source `protobuf_oneof:"source"`
// Types that are assignable to Dest: // Types that are assignable to Dest:
//
// *TransferRequest_DestAccountNumber // *TransferRequest_DestAccountNumber
// *TransferRequest_ExternalDest // *TransferRequest_ExternalDest
Dest isTransferRequest_Dest `protobuf_oneof:"dest"` Dest isTransferRequest_Dest `protobuf_oneof:"dest"`
@ -1345,3 +1347,355 @@ func file_bank_proto_init() {
file_bank_proto_goTypes = nil file_bank_proto_goTypes = nil
file_bank_proto_depIdxs = nil file_bank_proto_depIdxs = nil
} }
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// BankClient is the client API for Bank service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#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.
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)
}
// UnimplementedBankServer can 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 RegisterBankServer(s *grpc.Server, 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)
}
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",
}

View File

@ -1,374 +0,0 @@
// 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",
}

View File

@ -15,7 +15,6 @@ import (
// a capability to connect customers and support agents in real-time // a capability to connect customers and support agents in real-time
// chat. // chat.
type chatServer struct { type chatServer struct {
UnimplementedSupportServer
chatsBySession map[string]*session chatsBySession map[string]*session
chatsAwaitingAgent []string chatsAwaitingAgent []string
lastSession int32 lastSession int32

View File

@ -1,12 +1,13 @@
package main package main
//go:generate protoc --go_out=. --go-grpc_out=. bank.proto support.proto //go:generate protoc --go_out=plugins=grpc:./ bank.proto support.proto
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"net" "net"
"os" "os"
"os/signal" "os/signal"
@ -129,7 +130,7 @@ type svr struct {
} }
func (s *svr) load() error { func (s *svr) load() error {
accts, err := os.ReadFile(s.datafile) accts, err := ioutil.ReadFile(s.datafile)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return err return err
} }
@ -161,7 +162,7 @@ func (s *svr) flush() {
if b, err := json.Marshal(accounts); err != nil { if b, err := json.Marshal(accounts); err != nil {
grpclog.Errorf("failed to save data to %q", s.datafile) grpclog.Errorf("failed to save data to %q", s.datafile)
} else if err := os.WriteFile(s.datafile, b, 0666); err != nil { } else if err := ioutil.WriteFile(s.datafile, b, 0666); err != nil {
grpclog.Errorf("failed to save data to %q", s.datafile) grpclog.Errorf("failed to save data to %q", s.datafile)
} }
} }

View File

@ -1,13 +1,17 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.25.0-devel // protoc-gen-go v1.25.0-devel
// protoc v4.22.0 // protoc v3.14.0
// source: support.proto // source: support.proto
package main package main
import ( import (
context "context"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb" timestamppb "google.golang.org/protobuf/types/known/timestamppb"
@ -75,7 +79,6 @@ type ChatCustomerRequest struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Types that are assignable to Req: // Types that are assignable to Req:
//
// *ChatCustomerRequest_Init // *ChatCustomerRequest_Init
// *ChatCustomerRequest_Msg // *ChatCustomerRequest_Msg
// *ChatCustomerRequest_HangUp // *ChatCustomerRequest_HangUp
@ -283,7 +286,6 @@ type ChatCustomerResponse struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Types that are assignable to Resp: // Types that are assignable to Resp:
//
// *ChatCustomerResponse_Session // *ChatCustomerResponse_Session
// *ChatCustomerResponse_Msg // *ChatCustomerResponse_Msg
Resp isChatCustomerResponse_Resp `protobuf_oneof:"resp"` Resp isChatCustomerResponse_Resp `protobuf_oneof:"resp"`
@ -369,7 +371,6 @@ type ChatAgentRequest struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Types that are assignable to Req: // Types that are assignable to Req:
//
// *ChatAgentRequest_Accept // *ChatAgentRequest_Accept
// *ChatAgentRequest_Msg // *ChatAgentRequest_Msg
// *ChatAgentRequest_LeaveSession // *ChatAgentRequest_LeaveSession
@ -523,7 +524,6 @@ type ChatEntry struct {
Date *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty"` Date *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty"`
// Types that are assignable to Entry: // Types that are assignable to Entry:
//
// *ChatEntry_CustomerMsg // *ChatEntry_CustomerMsg
// *ChatEntry_AgentMsg // *ChatEntry_AgentMsg
Entry isChatEntry_Entry `protobuf_oneof:"entry"` Entry isChatEntry_Entry `protobuf_oneof:"entry"`
@ -611,7 +611,6 @@ type ChatAgentResponse struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Types that are assignable to Resp: // Types that are assignable to Resp:
//
// *ChatAgentResponse_AcceptedSession // *ChatAgentResponse_AcceptedSession
// *ChatAgentResponse_Msg // *ChatAgentResponse_Msg
// *ChatAgentResponse_SessionEnded // *ChatAgentResponse_SessionEnded
@ -1057,3 +1056,199 @@ func file_support_proto_init() {
file_support_proto_goTypes = nil file_support_proto_goTypes = nil
file_support_proto_depIdxs = nil file_support_proto_depIdxs = nil
} }
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// SupportClient is the client API for Support service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#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.
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
}
// UnimplementedSupportServer can 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 RegisterSupportServer(s *grpc.Server, 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
}
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",
}

View File

@ -1,217 +0,0 @@
// 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",
}

View File

@ -1,4 +1,3 @@
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris // +build darwin dragonfly freebsd linux netbsd openbsd solaris
package main package main

Binary file not shown.

View File

@ -20,13 +20,17 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.25.0-devel // protoc-gen-go v1.25.0-devel
// protoc v4.22.0 // protoc v3.14.0
// source: test.proto // source: test.proto
package testing package testing
import ( import (
context "context"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect" reflect "reflect"
@ -1028,3 +1032,491 @@ func file_test_proto_init() {
file_test_proto_goTypes = nil file_test_proto_goTypes = nil
file_test_proto_depIdxs = nil file_test_proto_depIdxs = nil
} }
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// TestServiceClient is the client API for TestService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#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.
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
}
// UnimplementedTestServiceServer can 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 RegisterTestServiceServer(s *grpc.Server, 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
}
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://godoc.org/google.golang.org/grpc#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.
type UnimplementedServiceServer interface {
// A call that no server should implement
UnimplementedCall(context.Context, *Empty) (*Empty, error)
}
// UnimplementedUnimplementedServiceServer can 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 RegisterUnimplementedServiceServer(s *grpc.Server, 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)
}
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",
}

View File

@ -1,523 +0,0 @@
// 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",
}

View File

@ -1,6 +1,6 @@
package testing package testing
//go:generate protoc --go_out=. --go-grpc_out=. test.proto //go:generate protoc --go_out=plugins=grpc:./ test.proto
//go:generate protoc --descriptor_set_out=./test.protoset test.proto //go:generate protoc --descriptor_set_out=./test.protoset test.proto
//go:generate protoc --descriptor_set_out=./example.protoset --include_imports example.proto //go:generate protoc --descriptor_set_out=./example.protoset --include_imports example.proto
@ -19,9 +19,7 @@ import (
) )
// TestServer implements the TestService interface defined in example.proto. // 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. // EmptyCall accepts one empty request and issues one empty response.
func (TestServer) EmptyCall(ctx context.Context, req *Empty) (*Empty, error) { func (TestServer) EmptyCall(ctx context.Context, req *Empty) (*Empty, error) {

View File

@ -9,10 +9,10 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"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/jsonpb" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/golang/protobuf/proto" //lint:ignore SA1019 same as above "github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/dynamic" //lint:ignore SA1019 same as above "github.com/jhump/protoreflect/dynamic"
"github.com/jhump/protoreflect/dynamic/grpcdynamic" "github.com/jhump/protoreflect/dynamic/grpcdynamic"
"github.com/jhump/protoreflect/grpcreflect" "github.com/jhump/protoreflect/grpcreflect"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -264,11 +264,9 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
// Now we can actually invoke the RPC! // Now we can actually invoke the RPC!
str, err := stub.InvokeRpcServerStream(ctx, md, req) str, err := stub.InvokeRpcServerStream(ctx, md, req)
if str != nil {
if respHeaders, err := str.Header(); err == nil { if respHeaders, err := str.Header(); err == nil {
handler.OnReceiveHeaders(respHeaders) handler.OnReceiveHeaders(respHeaders)
} }
}
// Download each response message // Download each response message
for err == nil { for err == nil {
@ -290,9 +288,7 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err) return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err)
} }
if str != nil {
handler.OnReceiveTrailers(stat, str.Trailer()) handler.OnReceiveTrailers(stat, str.Trailer())
}
return nil return nil
} }

View File

@ -53,7 +53,18 @@ This will create the release in GitHub with provisional release notes that just
### Docker Hub Releases ### Docker Hub Releases
To re-run only the Docker Hub release steps, you can manually run through each step in the "Docker" section of `do_release.sh`. 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
```
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. 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.
@ -63,7 +74,7 @@ The last step is to update the Homebrew recipe to use the latest version. First,
```sh ```sh
# download the source archive from GitHub # download the source archive from GitHub
URL=https://github.com/fullstorydev/grpcurl/archive/refs/tags/v2.3.4.tar.gz URL=https://github.com/fullstorydev/grpcurl/archive/v2.3.4.tar.gz
curl -L -o tmp.tgz $URL curl -L -o tmp.tgz $URL
# and compute the SHA # and compute the SHA
SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')" SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')"

View File

@ -49,13 +49,12 @@ $PREFIX docker run --privileged --rm tonistiigi/binfmt:qemu-v6.1.0 --install all
export DOCKER_CLI_EXPERIMENTAL=enabled export DOCKER_CLI_EXPERIMENTAL=enabled
$PREFIX docker buildx create --use --name multiarch-builder --node multiarch-builder0 $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 # push to docker hub, both the given version as a tag and for "latest" tag
$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/arm64 --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 rm VERSION
# Homebrew release # Homebrew release
URL="https://github.com/fullstorydev/grpcurl/archive/refs/tags/${VERSION}.tar.gz" URL="https://github.com/fullstorydev/grpcurl/archive/${VERSION}.tar.gz"
curl -L -o tmp.tgz "$URL" curl -L -o tmp.tgz "$URL"
SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')" SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')"
rm tmp.tgz rm tmp.tgz

View File

@ -1,23 +0,0 @@
# 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!

View File

@ -1,47 +0,0 @@
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

View File

@ -170,8 +170,8 @@ func TestBrokenTLS_ServerPlainText(t *testing.T) {
e, err := createTestServerAndClient(nil, clientCreds) e, err := createTestServerAndClient(nil, clientCreds)
if err == nil { if err == nil {
e.Close()
t.Fatal("expecting TLS failure setting up server and client") t.Fatal("expecting TLS failure setting up server and client")
e.Close()
} }
if !strings.Contains(err.Error(), "first record does not look like a TLS handshake") { if !strings.Contains(err.Error(), "first record does not look like a TLS handshake") {
t.Fatalf("expecting TLS handshake failure, got: %v", err) t.Fatalf("expecting TLS handshake failure, got: %v", err)
@ -190,8 +190,8 @@ func TestBrokenTLS_ServerUsesWrongCert(t *testing.T) {
e, err := createTestServerAndClient(serverCreds, clientCreds) e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil { if err == nil {
e.Close()
t.Fatal("expecting TLS failure setting up server and client") t.Fatal("expecting TLS failure setting up server and client")
e.Close()
} }
if !strings.Contains(err.Error(), "certificate is valid for") { if !strings.Contains(err.Error(), "certificate is valid for") {
t.Fatalf("expecting TLS certificate error, got: %v", err) t.Fatalf("expecting TLS certificate error, got: %v", err)
@ -210,10 +210,10 @@ func TestBrokenTLS_ClientHasExpiredCert(t *testing.T) {
e, err := createTestServerAndClient(serverCreds, clientCreds) e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil { if err == nil {
e.Close()
t.Fatal("expecting TLS failure setting up server and client") t.Fatal("expecting TLS failure setting up server and client")
e.Close()
} }
if !strings.Contains(err.Error(), "certificate") { if !strings.Contains(err.Error(), "bad certificate") {
t.Fatalf("expecting TLS certificate error, got: %v", err) t.Fatalf("expecting TLS certificate error, got: %v", err)
} }
} }
@ -230,8 +230,8 @@ func TestBrokenTLS_ServerHasExpiredCert(t *testing.T) {
e, err := createTestServerAndClient(serverCreds, clientCreds) e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil { if err == nil {
e.Close()
t.Fatal("expecting TLS failure setting up server and client") t.Fatal("expecting TLS failure setting up server and client")
e.Close()
} }
if !strings.Contains(err.Error(), "certificate has expired or is not yet valid") { if !strings.Contains(err.Error(), "certificate has expired or is not yet valid") {
t.Fatalf("expecting TLS certificate expired, got: %v", err) t.Fatalf("expecting TLS certificate expired, got: %v", err)
@ -250,15 +250,11 @@ func TestBrokenTLS_ClientNotTrusted(t *testing.T) {
e, err := createTestServerAndClient(serverCreds, clientCreds) e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil { if err == nil {
e.Close()
t.Fatal("expecting TLS failure setting up server and client") t.Fatal("expecting TLS failure setting up server and client")
e.Close()
} }
// Check for either the old error (Go <=1.24) or the new one (Go 1.25+) if !strings.Contains(err.Error(), "bad certificate") {
// Go 1.24: "bad certificate" t.Fatalf("expecting TLS certificate error, got: %v", err)
// 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)
} }
} }
@ -274,10 +270,10 @@ func TestBrokenTLS_ServerNotTrusted(t *testing.T) {
e, err := createTestServerAndClient(serverCreds, clientCreds) e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil { if err == nil {
e.Close()
t.Fatal("expecting TLS failure setting up server and client") t.Fatal("expecting TLS failure setting up server and client")
e.Close()
} }
if !strings.Contains(err.Error(), "certificate") { if !strings.Contains(err.Error(), "certificate signed by unknown authority") {
t.Fatalf("expecting TLS certificate error, got: %v", err) t.Fatalf("expecting TLS certificate error, got: %v", err)
} }
} }
@ -294,15 +290,11 @@ func TestBrokenTLS_RequireClientCertButNonePresented(t *testing.T) {
e, err := createTestServerAndClient(serverCreds, clientCreds) e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil { if err == nil {
e.Close()
t.Fatal("expecting TLS failure setting up server and client") t.Fatal("expecting TLS failure setting up server and client")
e.Close()
} }
// Check for either the old error (Go <=1.24) or the new one (Go 1.25+) if !strings.Contains(err.Error(), "bad certificate") {
// Go 1.24: "bad certificate" t.Fatalf("expecting TLS certificate error, got: %v", err)
// 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)
} }
} }
@ -357,7 +349,7 @@ type testEnv struct {
cc *grpc.ClientConn cc *grpc.ClientConn
} }
func (e *testEnv) Close() { func (e testEnv) Close() {
if e.cc != nil { if e.cc != nil {
e.cc.Close() e.cc.Close()
e.cc = nil e.cc = nil