mirror of
https://github.com/fullstorydev/grpcurl.git
synced 2026-09-06 18:46:10 +03:00
Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf21d4aca5 | |||
| 8568146e02 | |||
| 7884ecb9c6 | |||
| aba598c119 | |||
| 4bb0f337c7 | |||
| 5f2d0c2dfc | |||
| 6be36ba632 | |||
| 353acfef45 | |||
| 04bf23be33 | |||
| 1a48043e8a | |||
| afea969b8a | |||
| 4ea1554ec7 | |||
| 0521a49a6a | |||
| cb68aaa7f5 | |||
| 2922de784b | |||
| f30a5a5545 | |||
| 5725f04a83 | |||
| c54eac28fd | |||
| 6caf0e77fa | |||
| 1ad1dc15dd | |||
| f575e91b2c | |||
| ed672b2bc9 | |||
| eab6c910a6 | |||
| 60e53f304f | |||
| f093930c85 | |||
| 7ad93a42d9 | |||
| 7155fb6211 | |||
| f28d506cea | |||
| 58ccc6321e | |||
| b519ffc959 | |||
| 3a8fa31879 | |||
| 614b1687cf | |||
| 30f87c1323 | |||
| 78655b4786 | |||
| d00c28104b | |||
| 9e3e083f29 | |||
| c32936d71e | |||
| f3c8ec2564 | |||
| 7e1a6c9068 | |||
| b9a11e9fea | |||
| bc5cf811a0 | |||
| fb49f049e6 | |||
| cdb43b08fa | |||
| 56181ba330 | |||
| 46c38b351a | |||
| a05d48d6dd | |||
| fc63514da1 | |||
| e14d9f769a | |||
| 239dde4a62 | |||
| 80e833a557 | |||
| 6fccd7757e | |||
| 400fa5f2d3 | |||
| 0e13e85e65 | |||
| 07361b21ea | |||
| 8e76884d21 | |||
| 805ce40c63 | |||
| 93ea011b36 | |||
| 5592211a41 | |||
| 184c8f70b5 | |||
| 149a93e0ec | |||
| 252b57fd45 | |||
| 24b80dfed8 | |||
| 334e3f56de | |||
| f4157743ed | |||
| 79fb35f680 | |||
| 7ccaf0a21f | |||
| 6093b09afa | |||
| 70c215f7e2 | |||
| 28c0ee28f0 | |||
| bc2944de97 | |||
| 7a845ca5e9 | |||
| c17f0782f7 | |||
| 42f63028d4 | |||
| 743e60a4c9 | |||
| b7a5d3bba8 | |||
| 2a29c1e64b | |||
| 9a59bed1d2 | |||
| ae7dadff19 | |||
| 3961a33e7f | |||
| d5b8e4d4ce | |||
| 0efcfa65f2 | |||
| fae58803d9 | |||
| 1fda47eb90 | |||
| 031cd3d1e7 | |||
| a5037bdf4a | |||
| 4775fb574b | |||
| b96cb4ddd0 | |||
| 006918123d | |||
| 66a2405833 | |||
| dfd889a44b | |||
| a3a5bcd8ab | |||
| 61a9c00d87 | |||
| 85f1cbf7ad | |||
| dd2f60135c | |||
| 81c624c41f | |||
| 3826617999 | |||
| 8d60b618ac | |||
| 47b842a805 | |||
| 898bdad041 | |||
| 25c896aa59 | |||
| 0d0992e6a2 | |||
| 8093376ece | |||
| fec466efa6 | |||
| 7f919e6459 | |||
| 0df5c93e8d | |||
| 353e0953cb | |||
| c9ac3da95f | |||
| ea24a77215 | |||
| c3fbeaff64 | |||
| 7860209a53 | |||
| b953ea196a | |||
| 683a7fb09c | |||
| 8bb6eeb0d0 | |||
| 805e231182 | |||
| aa5998a119 | |||
| b34b13bab3 | |||
| b890db745f | |||
| 57a2cd1a09 | |||
| ae7473c7a7 | |||
| b3f576068c | |||
| 8ee6c9423b | |||
| 4b65b3ee55 | |||
| 9ac7e3a34d |
+11
-33
@@ -4,59 +4,37 @@ shared_configs:
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
make deps test
|
||||
|
||||
make test
|
||||
|
||||
# Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference
|
||||
version: 2.1
|
||||
jobs:
|
||||
build-1-14:
|
||||
build-1-23:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/golang:1.14
|
||||
- image: cimg/go:1.23
|
||||
steps: *simple_job_steps
|
||||
|
||||
build-1-15:
|
||||
build-1-24:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/golang:1.15
|
||||
- image: cimg/go:1.24
|
||||
steps: *simple_job_steps
|
||||
|
||||
build-1-16:
|
||||
build-1-25:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/golang:1.16
|
||||
- image: cimg/go:1.25
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- go-mod-v4-{{ checksum "go.sum" }}
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: go mod download
|
||||
- save_cache:
|
||||
key: go-mod-v4-{{ checksum "go.sum" }}
|
||||
paths:
|
||||
- "/go/pkg/mod"
|
||||
- run:
|
||||
name: Run tests
|
||||
name: Run tests and linters
|
||||
command: |
|
||||
#mkdir -p /tmp/test-reports
|
||||
#gotestsum --junitfile /tmp/test-reports/unit-tests.xml
|
||||
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:
|
||||
pr-build-test:
|
||||
jobs:
|
||||
- build-1-14
|
||||
- build-1-15
|
||||
- build-1-16
|
||||
- build-1-17
|
||||
- build-1-23
|
||||
- build-1-24
|
||||
- build-1-25
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
# Check for updates once a week
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -0,0 +1,26 @@
|
||||
# Controls how GitHub groups merged PRs in the auto-generated release notes.
|
||||
# goreleaser delegates to GitHub's generator (changelog.use: github-native in
|
||||
# .goreleaser.yml), so this file is what shapes the notes for a release.
|
||||
#
|
||||
# Labels are optional: anything unlabeled lands in "Changes". Labeling a PR
|
||||
# `bug` or `enhancement` just sorts it into a nicer bucket, and dependabot
|
||||
# applies `dependencies` on its own, which keeps version bumps out of the way
|
||||
# at the bottom.
|
||||
changelog:
|
||||
exclude:
|
||||
labels:
|
||||
- ignore-for-release
|
||||
categories:
|
||||
- title: Enhancements
|
||||
labels:
|
||||
- enhancement
|
||||
- title: Bug Fixes
|
||||
labels:
|
||||
- bug
|
||||
- title: Dependencies
|
||||
labels:
|
||||
- dependencies
|
||||
# Catch-all. Must stay last: a PR lands in the first category it matches.
|
||||
- title: Changes
|
||||
labels:
|
||||
- "*"
|
||||
@@ -0,0 +1,22 @@
|
||||
# This workflow was added by CodeSee. Learn more at https://codesee.io/
|
||||
# This is v2.0 of this workflow file
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
name: CodeSee
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
codesee:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
name: Analyze the repo with CodeSee
|
||||
steps:
|
||||
- uses: Codesee-io/codesee-action@v2
|
||||
with:
|
||||
codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }}
|
||||
@@ -0,0 +1,184 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Release version, sem-ver format: vM.N.P"
|
||||
required: true
|
||||
type: string
|
||||
dry_run:
|
||||
description: "Build everything, publish nothing (aka DRY-RUN... no tag, no GitHub release, no image push, no brew PR)"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Only one release may be in flight at a time.
|
||||
concurrency:
|
||||
group: release
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Tag, build binaries, and create the GitHub release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write # create the tag and the release
|
||||
steps:
|
||||
- name: Validate version
|
||||
run: |
|
||||
if [[ ! "${{ inputs.version }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "::error::'${{ inputs.version }}' is not a sem-ver version of the form vM.N.P" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
# goreleaser needs full history (and existing tags) to compute the change log
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check that the tag does not already exist
|
||||
run: |
|
||||
if git rev-parse -q --verify "refs/tags/${{ inputs.version }}" >/dev/null; then
|
||||
echo "::error::tag ${{ inputs.version }} already exists" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/setup-go@v7
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
|
||||
# Releases are effectively immutable, so make sure we aren't shipping a broken build.
|
||||
- name: Run tests
|
||||
run: go test ./...
|
||||
|
||||
- name: Create tag
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git tag -a "${{ inputs.version }}" -m "Release ${{ inputs.version }}"
|
||||
|
||||
- name: Push tag
|
||||
if: ${{ !inputs.dry_run }}
|
||||
run: git push origin "${{ inputs.version }}"
|
||||
|
||||
# Cross-compiles for every platform in .goreleaser.yml, then creates the
|
||||
# GitHub release with generated notes and uploads the archives.
|
||||
- name: Build and release
|
||||
run: make release GORELEASER_ARGS="${{ inputs.dry_run && '--skip=publish,announce' || '' }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# CHANGELOG.md is the release notes that *would* have been published,
|
||||
# which is worth eyeballing before a real release.
|
||||
- name: Upload artifacts for inspection
|
||||
if: ${{ inputs.dry_run }}
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: dry-run-dist
|
||||
path: |
|
||||
dist/*.tar.gz
|
||||
dist/*.zip
|
||||
dist/*.txt
|
||||
dist/*.deb
|
||||
dist/*.rpm
|
||||
dist/CHANGELOG.md
|
||||
if-no-files-found: error
|
||||
|
||||
docker:
|
||||
name: Build and push the Docker image
|
||||
needs: release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write # push to ghcr.io
|
||||
outputs:
|
||||
image: ${{ steps.image.outputs.name }}
|
||||
env:
|
||||
# Matches what releasing/do-release.sh has always published.
|
||||
PLATFORMS: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le
|
||||
steps:
|
||||
# Derived from the repo rather than hardcoded, so this works the same on a
|
||||
# fork: `packages: write` only grants access to packages owned by the repo
|
||||
# owner. GHCR also rejects uppercase, and GitHub expressions have no
|
||||
# lowercase function, hence the shell parameter expansion.
|
||||
- name: Compute image name
|
||||
id: image
|
||||
run: echo "name=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
# the release job just created this tag; build the image from exactly that source
|
||||
ref: ${{ inputs.dry_run && github.sha || inputs.version }}
|
||||
|
||||
# The Dockerfile stamps the binary with the contents of this file. It is
|
||||
# gitignored, and produced by `make docker` during local builds.
|
||||
- name: Write VERSION file
|
||||
run: echo "${{ inputs.version }}" > VERSION
|
||||
|
||||
- uses: docker/setup-qemu-action@v4
|
||||
- uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
if: ${{ !inputs.dry_run }}
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# The Dockerfile has two final stages: the default `scratch` image and an
|
||||
# `alpine` one. Both are published, as do-release.sh does.
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
push: ${{ !inputs.dry_run }}
|
||||
no-cache: true
|
||||
tags: |
|
||||
${{ steps.image.outputs.name }}:${{ inputs.version }}
|
||||
${{ steps.image.outputs.name }}:latest
|
||||
|
||||
- name: Build and push (alpine)
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
target: alpine
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
push: ${{ !inputs.dry_run }}
|
||||
no-cache: true
|
||||
tags: |
|
||||
${{ steps.image.outputs.name }}:${{ inputs.version }}-alpine
|
||||
${{ steps.image.outputs.name }}:latest-alpine
|
||||
|
||||
summary:
|
||||
name: Summarize
|
||||
needs: [release, docker]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dry run summary
|
||||
if: ${{ inputs.dry_run }}
|
||||
run: |
|
||||
{
|
||||
echo "## Dry run of ${{ inputs.version }} succeeded"
|
||||
echo
|
||||
echo "Nothing was published. The binaries are attached to this run as the \`dry-run-dist\` artifact."
|
||||
echo "Re-run with **dry_run** unchecked to publish."
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Release summary
|
||||
if: ${{ !inputs.dry_run }}
|
||||
run: |
|
||||
{
|
||||
echo "## Released ${{ inputs.version }}"
|
||||
echo
|
||||
echo "* [GitHub release](${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ inputs.version }})"
|
||||
echo "* Image \`${{ needs.docker.outputs.image }}:${{ inputs.version }}\` (and \`:latest\`)"
|
||||
echo "* Image \`${{ needs.docker.outputs.image }}:${{ inputs.version }}-alpine\` (and \`:latest-alpine\`)"
|
||||
echo
|
||||
echo "Release notes were generated from the merged PRs. Nothing else to do."
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
@@ -1,3 +1,6 @@
|
||||
dist/
|
||||
.claude/
|
||||
.idea/
|
||||
VERSION
|
||||
.tmp/
|
||||
*.snap
|
||||
|
||||
+36
-5
@@ -1,3 +1,5 @@
|
||||
version: 2
|
||||
|
||||
builds:
|
||||
- binary: grpcurl
|
||||
main: ./cmd/grpcurl
|
||||
@@ -8,28 +10,57 @@ builds:
|
||||
goarch:
|
||||
- amd64
|
||||
- 386
|
||||
- arm
|
||||
- arm64
|
||||
- s390x
|
||||
- ppc64le
|
||||
goarm:
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: s390x
|
||||
- goos: windows
|
||||
goarch: s390x
|
||||
- goos: darwin
|
||||
goarch: ppc64le
|
||||
- goos: windows
|
||||
goarch: ppc64le
|
||||
ldflags:
|
||||
- -s -w -X main.version=v{{.Version}}
|
||||
|
||||
archives:
|
||||
- format: tar.gz
|
||||
name_template: >-
|
||||
{{ .Binary }}_{{ .Version }}_
|
||||
{{- if eq .Os "darwin" }}osx{{ else }}{{ .Os }}{{ end }}_
|
||||
{{- if eq .Arch "amd64" }}x86_64
|
||||
{{- else if eq .Arch "386" }}x86_32
|
||||
{{- else }}{{ .Arch }}{{ end }}
|
||||
{{- with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
replacements:
|
||||
amd64: x86_64
|
||||
386: x86_32
|
||||
darwin: osx
|
||||
files:
|
||||
- LICENSE
|
||||
|
||||
nfpms:
|
||||
- vendor: Fullstory
|
||||
homepage: https://github.com/fullstorydev/grpcurl/
|
||||
maintainer: Engineering at Fullstory <fixme@fixme>
|
||||
description: 'Like cURL, but for gRPC: Command-line tool for interacting with gRPC servers'
|
||||
license: MIT
|
||||
id: nfpms
|
||||
formats:
|
||||
- deb
|
||||
- rpm
|
||||
|
||||
changelog:
|
||||
use: github-native
|
||||
|
||||
+11
-2
@@ -1,5 +1,5 @@
|
||||
FROM golang:1.15-alpine as builder
|
||||
MAINTAINER FullStory Engineering
|
||||
FROM golang:1.25-alpine AS builder
|
||||
LABEL maintainer="Fullstory Engineering"
|
||||
|
||||
# create non-privileged group and user
|
||||
RUN addgroup -S grpcurl && adduser -S grpcurl -G grpcurl
|
||||
@@ -16,6 +16,15 @@ RUN go build -o /grpcurl \
|
||||
-ldflags "-w -extldflags \"-static\" -X \"main.version=$(cat VERSION)\"" \
|
||||
./cmd/grpcurl
|
||||
|
||||
FROM alpine:3 AS alpine
|
||||
WORKDIR /
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
COPY --from=builder /etc/passwd /etc/passwd
|
||||
COPY --from=builder /grpcurl /bin/grpcurl
|
||||
USER grpcurl
|
||||
|
||||
ENTRYPOINT ["/bin/grpcurl"]
|
||||
|
||||
# New FROM so we have a nice'n'tiny image
|
||||
FROM scratch
|
||||
WORKDIR /
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 FullStory, Inc
|
||||
Copyright (c) 2017 Fullstory, Inc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
|
||||
@@ -1,29 +1,42 @@
|
||||
dev_build_version=$(shell git describe --tags --always --dirty)
|
||||
|
||||
export PATH := $(shell pwd)/.tmp/protoc/bin:$(PATH)
|
||||
export PROTOC_VERSION := 22.0
|
||||
# Disable CGO for improved compatibility across distros
|
||||
export CGO_ENABLED=0
|
||||
export GOFLAGS=-trimpath
|
||||
export GOWORK=off
|
||||
|
||||
# TODO: run golint and errcheck, but only to catch *new* violations and
|
||||
# decide whether to change code or not (e.g. we need to be able to whitelist
|
||||
# violations already in the code). They can be useful to catch errors, but
|
||||
# they are just too noisy to be a requirement for a CI -- we don't even *want*
|
||||
# to fix some of the things they consider to be violations.
|
||||
.PHONY: ci
|
||||
ci: deps checkgofmt vet staticcheck ineffassign predeclared test
|
||||
ci: deps checkgofmt checkgenerate vet staticcheck ineffassign predeclared test
|
||||
|
||||
.PHONY: deps
|
||||
deps:
|
||||
go get -d -v -t ./...
|
||||
go mod tidy
|
||||
|
||||
.PHONY: updatedeps
|
||||
updatedeps:
|
||||
go get -d -v -t -u -f ./...
|
||||
go mod tidy
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
go install -ldflags '-X "main.version=dev build $(dev_build_version)"' ./...
|
||||
|
||||
GORELEASER_VERSION := v2.5.0
|
||||
# Extra flags for goreleaser, e.g. "--skip=publish" for a dry run.
|
||||
GORELEASER_ARGS ?=
|
||||
|
||||
.PHONY: release
|
||||
release:
|
||||
@go install github.com/goreleaser/goreleaser@v0.134.0
|
||||
goreleaser --rm-dist
|
||||
@go install github.com/goreleaser/goreleaser/v2@$(GORELEASER_VERSION)
|
||||
goreleaser release --clean $(GORELEASER_ARGS)
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
@@ -31,6 +44,22 @@ docker:
|
||||
docker build -t fullstorydev/grpcurl:$(dev_build_version) .
|
||||
@rm VERSION
|
||||
|
||||
.PHONY: generate
|
||||
generate: .tmp/protoc/bin/protoc
|
||||
@go install google.golang.org/protobuf/cmd/protoc-gen-go@a709e31e5d12
|
||||
@go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0
|
||||
@go install github.com/jhump/protoreflect/desc/sourceinfo/cmd/protoc-gen-gosrcinfo@v1.14.1
|
||||
go generate ./...
|
||||
go mod tidy
|
||||
|
||||
.PHONY: checkgenerate
|
||||
checkgenerate: generate
|
||||
git status --porcelain -- '**/*.go'
|
||||
@if [ -n "$$(git status --porcelain -- '**/*.go')" ]; then \
|
||||
git diff -- '**/*.go'; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: checkgofmt
|
||||
checkgofmt:
|
||||
gofmt -s -l .
|
||||
@@ -42,12 +71,10 @@ checkgofmt:
|
||||
vet:
|
||||
go vet ./...
|
||||
|
||||
# This all works fine with Go modules, but without modules,
|
||||
# CI is just getting latest master for dependencies like grpc.
|
||||
.PHONY: staticcheck
|
||||
staticcheck:
|
||||
@go install honnef.co/go/tools/cmd/staticcheck@v0.0.1-2020.1.4
|
||||
staticcheck ./...
|
||||
@go install honnef.co/go/tools/cmd/staticcheck@2025.1.1
|
||||
staticcheck -checks "inherit,-SA1019" ./...
|
||||
|
||||
.PHONY: ineffassign
|
||||
ineffassign:
|
||||
@@ -56,23 +83,25 @@ ineffassign:
|
||||
|
||||
.PHONY: predeclared
|
||||
predeclared:
|
||||
@go install github.com/nishanths/predeclared@86fad755b4d3
|
||||
predeclared .
|
||||
@go install github.com/nishanths/predeclared@51e8c974458a0f93dc03fe356f91ae1a6d791e6f
|
||||
predeclared ./...
|
||||
|
||||
# Intentionally omitted from CI, but target here for ad-hoc reports.
|
||||
.PHONY: golint
|
||||
golint:
|
||||
# TODO: pin version
|
||||
@go install golang.org/x/lint/golint@latest
|
||||
@go install golang.org/x/lint/golint@v0.0.0-20210508222113-6edffad5e616
|
||||
golint -min_confidence 0.9 -set_exit_status ./...
|
||||
|
||||
# Intentionally omitted from CI, but target here for ad-hoc reports.
|
||||
.PHONY: errcheck
|
||||
errcheck:
|
||||
# TODO: pin version
|
||||
@go install github.com/kisielk/errcheck@latest
|
||||
@go install github.com/kisielk/errcheck@v1.2.0
|
||||
errcheck ./...
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race ./...
|
||||
test: deps
|
||||
CGO_ENABLED=1 go test -race ./...
|
||||
|
||||
.tmp/protoc/bin/protoc: ./Makefile ./download_protoc.sh
|
||||
./download_protoc.sh
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# gRPCurl
|
||||
[](https://circleci.com/gh/fullstorydev/grpcurl/tree/master)
|
||||
[](https://goreportcard.com/report/github.com/fullstorydev/grpcurl)
|
||||
[](https://snapcraft.io/grpcurl)
|
||||
|
||||
`grpcurl` is a command-line tool that lets you interact with gRPC servers. It's
|
||||
basically `curl` for gRPC servers.
|
||||
@@ -14,7 +15,7 @@ This program accepts messages using JSON encoding, which is much more friendly f
|
||||
humans and scripts.
|
||||
|
||||
With this tool you can also browse the schema for gRPC services, either by querying
|
||||
a server that supports [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto),
|
||||
a server that supports [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto),
|
||||
by reading proto source files, or by loading in compiled "protoset" files (files that contain
|
||||
encoded file [descriptor protos](https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto)).
|
||||
In fact, the way the tool transforms JSON request data into a binary encoded protobuf
|
||||
@@ -61,9 +62,9 @@ brew install grpcurl
|
||||
For platforms that support Docker, you can download an image that lets you run `grpcurl`:
|
||||
```shell
|
||||
# Download image
|
||||
docker pull fullstorydev/grpcurl:latest
|
||||
docker pull ghcr.io/fullstorydev/grpcurl:latest
|
||||
# Run the tool
|
||||
docker run fullstorydev/grpcurl api.grpc.me:443 list
|
||||
docker run ghcr.io/fullstorydev/grpcurl api.grpc.me:443 list
|
||||
```
|
||||
Note that there are some pitfalls when using docker:
|
||||
- If you need to interact with a server listening on the host's loopback network, you must specify the host as `host.docker.internal` instead of `localhost` (for Mac or Windows) _OR_ have the container use the host network with `-network="host"` (Linux only).
|
||||
@@ -79,6 +80,12 @@ of environments, including Windows and myriad Linux distributions.
|
||||
You can see more details and the full list of other packages for `grpcurl` at _repology.org_:
|
||||
https://repology.org/project/grpcurl/information
|
||||
|
||||
### Snap
|
||||
|
||||
You can install `grpcurl` using the snap package:
|
||||
|
||||
`snap install grpcurl`
|
||||
|
||||
### From Source
|
||||
If you already have the [Go SDK](https://golang.org/doc/install) installed, you can use the `go`
|
||||
tool to install `grpcurl`:
|
||||
@@ -139,12 +146,19 @@ grpcurl -d @ grpc.server.com:443 my.custom.server.Service/Method <<EOM
|
||||
{
|
||||
"id": 1234,
|
||||
"tags": [
|
||||
"foor",
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
||||
EOM
|
||||
```
|
||||
### Adding Headers/Metadata to Request
|
||||
Adding of headers / metadata to a rpc request is possible via the `-H name:value` command line option. Multiple headers can be added in a similar fashion.
|
||||
Example :
|
||||
```shell
|
||||
grpcurl -H header1:value1 -H header2:value2 -d '{"id": 1234, "tags": ["foo","bar"]}' grpc.server.com:443 my.custom.server.Service/Method
|
||||
```
|
||||
For more usage guide, check out the help docs via `grpcurl -help`
|
||||
|
||||
### Listing Services
|
||||
To list all services exposed by a server, use the "list" verb. When using `.proto` source
|
||||
@@ -159,6 +173,13 @@ grpcurl -protoset my-protos.bin list
|
||||
|
||||
# Using proto sources
|
||||
grpcurl -import-path ../protos -proto my-stuff.proto list
|
||||
|
||||
# Export proto files (use -proto-out-dir to specify the output directory)
|
||||
grpcurl -plaintext -proto-out-dir "out_protos" "localhost:8787" describe my.custom.server.Service
|
||||
|
||||
# Export protoset file (use -protoset-out to specify the output file)
|
||||
grpcurl -plaintext -protoset-out "out.protoset" "localhost:8787" describe my.custom.server.Service
|
||||
|
||||
```
|
||||
|
||||
The "list" verb also lets you see all methods in a particular service:
|
||||
@@ -192,7 +213,7 @@ are needed to use them.
|
||||
|
||||
### Server Reflection
|
||||
|
||||
Without any additional command-line flags, `grpcurl` will try to use [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto).
|
||||
Without any additional command-line flags, `grpcurl` will try to use [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto).
|
||||
|
||||
Examples for how to set up server reflection can be found [here](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md#known-implementations).
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// +build go1.10
|
||||
|
||||
package main
|
||||
|
||||
func indent() string {
|
||||
// In Go 1.10 and up, the flag package automatically
|
||||
// adds the right indentation.
|
||||
return ""
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// +build !go1.10
|
||||
|
||||
package main
|
||||
|
||||
func indent() string {
|
||||
// In Go 1.9 and older, we need to add indentation
|
||||
// after newlines in the flag doc strings.
|
||||
return " \t"
|
||||
}
|
||||
+172
-35
@@ -8,6 +8,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -19,9 +20,9 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/alts"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
|
||||
@@ -33,14 +34,14 @@ import (
|
||||
"github.com/fullstorydev/grpcurl"
|
||||
)
|
||||
|
||||
// To avoid confusion between program error codes and the gRPC resonse
|
||||
// To avoid confusion between program error codes and the gRPC response
|
||||
// status codes 'Cancelled' and 'Unknown', 1 and 2 respectively,
|
||||
// the response status codes emitted use an offest of 64
|
||||
// the response status codes emitted use an offset of 64
|
||||
const statusCodeOffset = 64
|
||||
|
||||
const no_version = "dev build <no version set>"
|
||||
const noVersion = "dev build <no version set>"
|
||||
|
||||
var version = no_version
|
||||
var version = noVersion
|
||||
|
||||
var (
|
||||
exit = os.Exit
|
||||
@@ -53,11 +54,14 @@ var (
|
||||
Print usage instructions and exit.`))
|
||||
printVersion = flags.Bool("version", false, prettify(`
|
||||
Print version.`))
|
||||
|
||||
plaintext = flags.Bool("plaintext", false, prettify(`
|
||||
Use plain-text HTTP/2 when connecting to server (no TLS).`))
|
||||
insecure = flags.Bool("insecure", false, prettify(`
|
||||
Skip server certificate and domain verification. (NOT SECURE!) Not
|
||||
valid with -plaintext option.`))
|
||||
|
||||
// TLS Options
|
||||
cacert = flags.String("cacert", "", prettify(`
|
||||
File containing trusted root certificates for verifying the server.
|
||||
Ignored if -insecure is specified.`))
|
||||
@@ -67,6 +71,13 @@ var (
|
||||
key = flags.String("key", "", prettify(`
|
||||
File containing client private key, to present to the server. Not valid
|
||||
with -plaintext option. Must also provide -cert option.`))
|
||||
|
||||
// ALTS Options
|
||||
usealts = flags.Bool("alts", false, prettify(`
|
||||
Use Application Layer Transport Security (ALTS) when connecting to server.`))
|
||||
altsHandshakerServiceAddress = flags.String("alts-handshaker-service", "", prettify(`If set, this server will be used to do the ATLS handshaking.`))
|
||||
altsTargetServiceAccounts multiString
|
||||
|
||||
protoset multiString
|
||||
protoFiles multiString
|
||||
importPaths multiString
|
||||
@@ -87,7 +98,8 @@ var (
|
||||
value of the ":authority" pseudo-header in the HTTP/2 protocol. When TLS
|
||||
is used, this will also be used as the server name when verifying the
|
||||
server's certificate. It defaults to the address that is provided in the
|
||||
positional arguments.`))
|
||||
positional arguments, or 'localhost' in the case of a unix domain
|
||||
socket.`))
|
||||
userAgent = flags.String("user-agent", "", prettify(`
|
||||
If set, the specified value will be added to the User-Agent header set
|
||||
by the grpc-go library.
|
||||
@@ -109,7 +121,7 @@ var (
|
||||
separator.`))
|
||||
allowUnknownFields = flags.Bool("allow-unknown-fields", false, prettify(`
|
||||
When true, the request contents, if 'json' format is used, allows
|
||||
unkown fields to be present. They will be ignored when parsing
|
||||
unknown fields to be present. They will be ignored when parsing
|
||||
the request.`))
|
||||
connectTimeout = flags.Float64("connect-timeout", 0, prettify(`
|
||||
The maximum time, in seconds, to wait for connection to be established.
|
||||
@@ -123,9 +135,11 @@ var (
|
||||
is received for this same period then the connection is closed and the
|
||||
operation fails.`))
|
||||
maxTime = flags.Float64("max-time", 0, prettify(`
|
||||
The maximum total time the operation can take, in seconds. This is
|
||||
useful for preventing batch jobs that use grpcurl from hanging due to
|
||||
slow or bad network links or due to incorrect stream method usage.`))
|
||||
The maximum total time the operation can take, in seconds. This sets a
|
||||
timeout on the gRPC context, allowing both client and server to give up
|
||||
after the deadline has past. This is useful for preventing batch jobs
|
||||
that use grpcurl from hanging due to slow or bad network links or due
|
||||
to incorrect stream method usage.`))
|
||||
maxMsgSz = flags.Int("max-msg-sz", 0, prettify(`
|
||||
The maximum encoded size of a response message, in bytes, that grpcurl
|
||||
will accept. If not specified, defaults to 4,194,304 (4 megabytes).`))
|
||||
@@ -138,12 +152,20 @@ var (
|
||||
file if this option is given. When invoking an RPC and this option is
|
||||
given, the method being invoked and its transitive dependencies will be
|
||||
included in the output file.`))
|
||||
protoOut = flags.String("proto-out-dir", "", prettify(`
|
||||
The name of a directory where the generated .proto files will be written.
|
||||
With the list and describe verbs, the listed or described elements and
|
||||
their transitive dependencies will be written as .proto files in the
|
||||
specified directory if this option is given. When invoking an RPC and
|
||||
this option is given, the method being invoked and its transitive
|
||||
dependencies will be included in the generated .proto files in the
|
||||
output directory.`))
|
||||
msgTemplate = flags.Bool("msg-template", false, prettify(`
|
||||
When describing messages, show a template of input data.`))
|
||||
verbose = flags.Bool("v", false, prettify(`
|
||||
Enable verbose output.`))
|
||||
veryVerbose = flags.Bool("vv", false, prettify(`
|
||||
Enable very verbose output.`))
|
||||
Enable very verbose output (includes timing data).`))
|
||||
serverName = flags.String("servername", "", prettify(`
|
||||
Override server name when validating TLS certificate. This flag is
|
||||
ignored if -plaintext or -insecure is used.
|
||||
@@ -200,6 +222,14 @@ func init() {
|
||||
-use-reflection is used in combination with a -proto or -protoset flag,
|
||||
the provided descriptor sources will be used in addition to server
|
||||
reflection to resolve messages and extensions.`))
|
||||
flags.Var(&altsTargetServiceAccounts, "alts-target-service-account", prettify(`
|
||||
The full email address of the service account that the server is
|
||||
expected to be using when ALTS is used. You can specify this option
|
||||
multiple times to indicate multiple allowed service accounts. If the
|
||||
server authenticates with a service account that is not one of the
|
||||
expected accounts, the RPC will not be issued. If no such arguments are
|
||||
provided, no check will be performed, and the RPC will be issued
|
||||
regardless of the server's service account.`))
|
||||
}
|
||||
|
||||
type multiString []string
|
||||
@@ -256,6 +286,32 @@ func (cs compositeSource) AllExtensionsForType(typeName string) ([]*desc.FieldDe
|
||||
return exts, nil
|
||||
}
|
||||
|
||||
type timingData struct {
|
||||
Title string
|
||||
Start time.Time
|
||||
Value time.Duration
|
||||
Parent *timingData
|
||||
Sub []*timingData
|
||||
}
|
||||
|
||||
func (d *timingData) Child(title string) *timingData {
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
child := &timingData{Title: title, Start: time.Now()}
|
||||
d.Sub = append(d.Sub, child)
|
||||
return child
|
||||
}
|
||||
|
||||
func (d *timingData) Done() {
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
if d.Value == 0 {
|
||||
d.Value = time.Since(d.Start)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flags.Usage = usage
|
||||
flags.Parse(os.Args[1:])
|
||||
@@ -268,6 +324,9 @@ func main() {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// default behavior is to use tls
|
||||
usetls := !*plaintext && !*usealts
|
||||
|
||||
// Do extra validation on arguments and figure out what user asked us to do.
|
||||
if *connectTimeout < 0 {
|
||||
fail(nil, "The -connect-timeout argument must not be negative.")
|
||||
@@ -281,18 +340,27 @@ func main() {
|
||||
if *maxMsgSz < 0 {
|
||||
fail(nil, "The -max-msg-sz argument must not be negative.")
|
||||
}
|
||||
if *plaintext && *insecure {
|
||||
fail(nil, "The -plaintext and -insecure arguments are mutually exclusive.")
|
||||
if *plaintext && *usealts {
|
||||
fail(nil, "The -plaintext and -alts arguments are mutually exclusive.")
|
||||
}
|
||||
if *plaintext && *cert != "" {
|
||||
fail(nil, "The -plaintext and -cert arguments are mutually exclusive.")
|
||||
if *insecure && !usetls {
|
||||
fail(nil, "The -insecure argument can only be used with TLS.")
|
||||
}
|
||||
if *plaintext && *key != "" {
|
||||
fail(nil, "The -plaintext and -key arguments are mutually exclusive.")
|
||||
if *cert != "" && !usetls {
|
||||
fail(nil, "The -cert argument can only be used with TLS.")
|
||||
}
|
||||
if *key != "" && !usetls {
|
||||
fail(nil, "The -key argument can only be used with TLS.")
|
||||
}
|
||||
if (*key == "") != (*cert == "") {
|
||||
fail(nil, "The -cert and -key arguments must be used together and both be present.")
|
||||
}
|
||||
if *altsHandshakerServiceAddress != "" && !*usealts {
|
||||
fail(nil, "The -alts-handshaker-service argument must be used with the -alts argument.")
|
||||
}
|
||||
if len(altsTargetServiceAccounts) > 0 && !*usealts {
|
||||
fail(nil, "The -alts-target-service-account argument must be used with the -alts argument.")
|
||||
}
|
||||
if *format != "json" && *format != "text" {
|
||||
fail(nil, "The -format option must be 'json' or 'text'.")
|
||||
}
|
||||
@@ -329,8 +397,16 @@ func main() {
|
||||
if *verbose {
|
||||
verbosityLevel = 1
|
||||
}
|
||||
|
||||
var rootTiming *timingData
|
||||
if *veryVerbose {
|
||||
verbosityLevel = 2
|
||||
|
||||
rootTiming = &timingData{Title: "Timing Data", Start: time.Now()}
|
||||
defer func() {
|
||||
rootTiming.Done()
|
||||
dumpTiming(rootTiming, 0)
|
||||
}()
|
||||
}
|
||||
|
||||
var symbol string
|
||||
@@ -382,22 +458,24 @@ func main() {
|
||||
|
||||
ctx := context.Background()
|
||||
if *maxTime > 0 {
|
||||
timeout := time.Duration(*maxTime * float64(time.Second))
|
||||
timeout := floatSecondsToDuration(*maxTime)
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
dial := func() *grpc.ClientConn {
|
||||
dialTiming := rootTiming.Child("Dial")
|
||||
defer dialTiming.Done()
|
||||
dialTime := 10 * time.Second
|
||||
if *connectTimeout > 0 {
|
||||
dialTime = time.Duration(*connectTimeout * float64(time.Second))
|
||||
dialTime = floatSecondsToDuration(*connectTimeout)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, dialTime)
|
||||
defer cancel()
|
||||
var opts []grpc.DialOption
|
||||
if *keepaliveTime > 0 {
|
||||
timeout := time.Duration(*keepaliveTime * float64(time.Second))
|
||||
timeout := floatSecondsToDuration(*keepaliveTime)
|
||||
opts = append(opts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||
Time: timeout,
|
||||
Timeout: timeout,
|
||||
@@ -406,8 +484,31 @@ func main() {
|
||||
if *maxMsgSz > 0 {
|
||||
opts = append(opts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(*maxMsgSz)))
|
||||
}
|
||||
if isUnixSocket != nil && isUnixSocket() && !strings.HasPrefix(target, "unix://") {
|
||||
// prepend unix:// to the address if it's not already there
|
||||
// this is to maintain backwards compatibility because the custom dialer is replaced by
|
||||
// the default dialer in grpc-go.
|
||||
// https://github.com/fullstorydev/grpcurl/pull/480
|
||||
target = "unix://" + target
|
||||
}
|
||||
var creds credentials.TransportCredentials
|
||||
if !*plaintext {
|
||||
if *plaintext {
|
||||
if *authority != "" {
|
||||
opts = append(opts, grpc.WithAuthority(*authority))
|
||||
}
|
||||
} else if *usealts {
|
||||
clientOptions := alts.DefaultClientOptions()
|
||||
if len(altsTargetServiceAccounts) > 0 {
|
||||
clientOptions.TargetServiceAccounts = altsTargetServiceAccounts
|
||||
}
|
||||
if *altsHandshakerServiceAddress != "" {
|
||||
clientOptions.HandshakerServiceAddress = *altsHandshakerServiceAddress
|
||||
}
|
||||
creds = alts.NewClientCreds(clientOptions)
|
||||
} else if usetls {
|
||||
tlsTiming := dialTiming.Child("TLS Setup")
|
||||
defer tlsTiming.Done()
|
||||
|
||||
tlsConf, err := grpcurl.ClientTLSConfig(*insecure, *cacert, *cert, *key)
|
||||
if err != nil {
|
||||
fail(err, "Failed to create TLS config")
|
||||
@@ -422,7 +523,7 @@ func main() {
|
||||
tlsConf.KeyLogWriter = w
|
||||
}
|
||||
|
||||
creds := credentials.NewTLS(tlsConf)
|
||||
creds = credentials.NewTLS(tlsConf)
|
||||
|
||||
// can use either -servername or -authority; but not both
|
||||
if *serverName != "" && *authority != "" {
|
||||
@@ -438,16 +539,15 @@ func main() {
|
||||
}
|
||||
|
||||
if overrideName != "" {
|
||||
if err := creds.OverrideServerName(overrideName); err != nil {
|
||||
fail(err, "Failed to override server name as %q", overrideName)
|
||||
}
|
||||
opts = append(opts, grpc.WithAuthority(overrideName))
|
||||
}
|
||||
} else if *authority != "" {
|
||||
opts = append(opts, grpc.WithAuthority(*authority))
|
||||
tlsTiming.Done()
|
||||
} else {
|
||||
panic("Should have defaulted to use TLS.")
|
||||
}
|
||||
|
||||
grpcurlUA := "grpcurl/" + version
|
||||
if version == no_version {
|
||||
if version == noVersion {
|
||||
grpcurlUA = "grpcurl/dev-build (no version set)"
|
||||
}
|
||||
if *userAgent != "" {
|
||||
@@ -455,11 +555,9 @@ func main() {
|
||||
}
|
||||
opts = append(opts, grpc.WithUserAgent(grpcurlUA))
|
||||
|
||||
network := "tcp"
|
||||
if isUnixSocket != nil && isUnixSocket() {
|
||||
network = "unix"
|
||||
}
|
||||
cc, err := grpcurl.BlockingDial(ctx, network, target, creds, opts...)
|
||||
blockingDialTiming := dialTiming.Child("BlockingDial")
|
||||
defer blockingDialTiming.Done()
|
||||
cc, err := grpcurl.BlockingDial(ctx, "", target, creds, opts...)
|
||||
if err != nil {
|
||||
fail(err, "Failed to dial target host %q", target)
|
||||
}
|
||||
@@ -510,7 +608,8 @@ func main() {
|
||||
md := grpcurl.MetadataFromHeaders(append(addlHeaders, reflHeaders...))
|
||||
refCtx := metadata.NewOutgoingContext(ctx, md)
|
||||
cc = dial()
|
||||
refClient = grpcreflect.NewClient(refCtx, reflectpb.NewServerReflectionClient(cc))
|
||||
refClient = grpcreflect.NewClientAuto(refCtx, cc)
|
||||
refClient.AllowMissingFileDescriptors()
|
||||
reflSource := grpcurl.DescriptorSourceFromServer(ctx, refClient)
|
||||
if fileSource != nil {
|
||||
descSource = compositeSource{reflSource, fileSource}
|
||||
@@ -555,6 +654,9 @@ func main() {
|
||||
if err := writeProtoset(descSource, svcs...); err != nil {
|
||||
fail(err, "Failed to write protoset to %s", *protosetOut)
|
||||
}
|
||||
if err := writeProtos(descSource, svcs...); err != nil {
|
||||
fail(err, "Failed to write protos to %s", *protoOut)
|
||||
}
|
||||
} else {
|
||||
methods, err := grpcurl.ListMethods(descSource, symbol)
|
||||
if err != nil {
|
||||
@@ -570,6 +672,9 @@ func main() {
|
||||
if err := writeProtoset(descSource, symbol); err != nil {
|
||||
fail(err, "Failed to write protoset to %s", *protosetOut)
|
||||
}
|
||||
if err := writeProtos(descSource, symbol); err != nil {
|
||||
fail(err, "Failed to write protos to %s", *protoOut)
|
||||
}
|
||||
}
|
||||
|
||||
} else if describe {
|
||||
@@ -674,6 +779,9 @@ func main() {
|
||||
if err := writeProtoset(descSource, symbols...); err != nil {
|
||||
fail(err, "Failed to write protoset to %s", *protosetOut)
|
||||
}
|
||||
if err := writeProtos(descSource, symbol); err != nil {
|
||||
fail(err, "Failed to write protos to %s", *protoOut)
|
||||
}
|
||||
|
||||
} else {
|
||||
// Invoke an RPC
|
||||
@@ -706,7 +814,9 @@ func main() {
|
||||
VerbosityLevel: verbosityLevel,
|
||||
}
|
||||
|
||||
invokeTiming := rootTiming.Child("InvokeRPC")
|
||||
err = grpcurl.InvokeRPC(ctx, descSource, cc, symbol, append(addlHeaders, rpcHeaders...), h, rf.Next)
|
||||
invokeTiming.Done()
|
||||
if err != nil {
|
||||
if errStatus, ok := status.FromError(err); ok && *formatError {
|
||||
h.Status = errStatus
|
||||
@@ -737,6 +847,17 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func dumpTiming(td *timingData, lvl int) {
|
||||
var ind strings.Builder
|
||||
for x := 0; x < lvl; x++ {
|
||||
ind.WriteString(" ")
|
||||
}
|
||||
fmt.Printf("%s%s: %s\n", ind.String(), td.Title, td.Value)
|
||||
for _, sd := range td.Sub {
|
||||
dumpTiming(sd, lvl+1)
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, `Usage:
|
||||
%s [flags] [address] [list|describe] [symbol]
|
||||
@@ -784,7 +905,7 @@ func prettify(docString string) string {
|
||||
j++
|
||||
}
|
||||
|
||||
return strings.Join(parts[:j], "\n"+indent())
|
||||
return strings.Join(parts[:j], "\n")
|
||||
}
|
||||
|
||||
func warn(msg string, args ...interface{}) {
|
||||
@@ -820,6 +941,13 @@ func writeProtoset(descSource grpcurl.DescriptorSource, symbols ...string) error
|
||||
return grpcurl.WriteProtoset(f, descSource, symbols...)
|
||||
}
|
||||
|
||||
func writeProtos(descSource grpcurl.DescriptorSource, symbols ...string) error {
|
||||
if *protoOut == "" {
|
||||
return nil
|
||||
}
|
||||
return grpcurl.WriteProtoFiles(*protoOut, descSource, symbols...)
|
||||
}
|
||||
|
||||
type optionalBoolFlag struct {
|
||||
set, val bool
|
||||
}
|
||||
@@ -844,3 +972,12 @@ func (f *optionalBoolFlag) Set(s string) error {
|
||||
func (f *optionalBoolFlag) IsBoolFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func floatSecondsToDuration(seconds float64) time.Duration {
|
||||
durationFloat := seconds * float64(time.Second)
|
||||
if durationFloat > math.MaxInt64 {
|
||||
// Avoid overflow
|
||||
return math.MaxInt64
|
||||
}
|
||||
return time.Duration(durationFloat)
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows
|
||||
|
||||
package main
|
||||
|
||||
|
||||
+94
-16
@@ -5,12 +5,14 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/desc/protoparse"
|
||||
"github.com/jhump/protoreflect/desc/protoprint"
|
||||
"github.com/jhump/protoreflect/dynamic"
|
||||
"github.com/jhump/protoreflect/grpcreflect"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -41,7 +43,7 @@ type DescriptorSource interface {
|
||||
func DescriptorSourceFromProtoSets(fileNames ...string) (DescriptorSource, error) {
|
||||
files := &descriptorpb.FileDescriptorSet{}
|
||||
for _, fileName := range fileNames {
|
||||
b, err := ioutil.ReadFile(fileName)
|
||||
b, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not load protoset file %q: %v", fileName, err)
|
||||
}
|
||||
@@ -258,19 +260,9 @@ func reflectionSupport(err error) error {
|
||||
// given output. The output will include descriptors for all files in which the
|
||||
// symbols are defined as well as their transitive dependencies.
|
||||
func WriteProtoset(out io.Writer, descSource DescriptorSource, symbols ...string) error {
|
||||
// compute set of file descriptors
|
||||
filenames := make([]string, 0, len(symbols))
|
||||
fds := make(map[string]*desc.FileDescriptor, len(symbols))
|
||||
for _, sym := range symbols {
|
||||
d, err := descSource.FindSymbol(sym)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find descriptor for %q: %v", sym, err)
|
||||
}
|
||||
fd := d.GetFile()
|
||||
if _, ok := fds[fd.GetName()]; !ok {
|
||||
fds[fd.GetName()] = fd
|
||||
filenames = append(filenames, fd.GetName())
|
||||
}
|
||||
filenames, fds, err := getFileDescriptors(symbols, descSource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// now expand that to include transitive dependencies in topologically sorted
|
||||
// order (such that file always appears after its dependencies)
|
||||
@@ -302,3 +294,89 @@ func addFilesToSet(allFiles []*descriptorpb.FileDescriptorProto, expanded map[st
|
||||
}
|
||||
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])
|
||||
}
|
||||
return writeProtoFiles(outProtoDirPath, allFileDescriptors)
|
||||
}
|
||||
|
||||
func writeProtoFiles(outProtoDirPath string, allFileDescriptors []*desc.FileDescriptor) error {
|
||||
if err := os.MkdirAll(outProtoDirPath, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create output directory %q: %w", outProtoDirPath, err)
|
||||
}
|
||||
root, err := os.OpenRoot(outProtoDirPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open output directory %q: %w", outProtoDirPath, err)
|
||||
}
|
||||
defer root.Close()
|
||||
pr := protoprint.Printer{}
|
||||
// now we can serialize to files
|
||||
for i := range allFileDescriptors {
|
||||
if err := writeProtoFile(root, allFileDescriptors[i], &pr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeProtoFile(root *os.Root, fd *desc.FileDescriptor, pr *protoprint.Printer) error {
|
||||
// root confines all path operations to the output directory, so a
|
||||
// malicious file name (e.g. "../escape.proto") cannot write outside it
|
||||
outFile := fd.GetFullyQualifiedName()
|
||||
if err := root.MkdirAll(filepath.Dir(outFile), 0755); err != nil {
|
||||
return fmt.Errorf("failed to create directory for %q: %w", outFile, err)
|
||||
}
|
||||
|
||||
f, err := root.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)
|
||||
}
|
||||
|
||||
+49
-3
@@ -2,10 +2,12 @@ package grpcurl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"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"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
@@ -34,7 +36,7 @@ func TestWriteProtoset(t *testing.T) {
|
||||
}
|
||||
|
||||
func loadProtoset(path string) (*descriptorpb.FileDescriptorSet, error) {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -60,3 +62,47 @@ func checkWriteProtoset(t *testing.T, descSrc DescriptorSource, protoset *descri
|
||||
t.Fatalf("written protoset not equal to input:\nExpecting: %s\nActual: %s", protoset, &result)
|
||||
}
|
||||
}
|
||||
|
||||
func writeProtoFileForTest(t *testing.T, dir, fdName string) error {
|
||||
t.Helper()
|
||||
fd, err := desc.CreateFileDescriptor(&descriptorpb.FileDescriptorProto{
|
||||
Name: proto.String(fdName),
|
||||
Syntax: proto.String("proto3"),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create file descriptor: %v", err)
|
||||
}
|
||||
return writeProtoFiles(dir, []*desc.FileDescriptor{fd})
|
||||
}
|
||||
|
||||
func TestWriteProtoFile_NormalPath(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if err := writeProtoFileForTest(t, dir, "foo/bar.proto"); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(dir, "foo", "bar.proto")); err != nil {
|
||||
t.Fatalf("expected output file not created: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteProtoFile_RejectsPathTraversal(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if err := writeProtoFileForTest(t, dir, "../escape.proto"); err == nil {
|
||||
t.Fatal("expected error for path-traversing descriptor name, got nil")
|
||||
}
|
||||
escapePath := filepath.Join(dir, "..", "escape.proto")
|
||||
if _, err := os.Stat(escapePath); err == nil {
|
||||
t.Fatalf("file was created outside output directory at %q", escapePath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteProtoFile_RejectsDeepPathTraversal(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if err := writeProtoFileForTest(t, dir, "foo/../../../escape.proto"); err == nil {
|
||||
t.Fatal("expected error for path-traversing descriptor name, got nil")
|
||||
}
|
||||
escapePath := filepath.Join(dir, "foo", "..", "..", "..", "escape.proto")
|
||||
if _, err := os.Stat(escapePath); err == nil {
|
||||
t.Fatalf("file was created outside output directory at %q", escapePath)
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
if [[ -z "$PROTOC_VERSION" ]]; then
|
||||
echo "Set PROTOC_VERSION env var to indicate the version to download" >&2
|
||||
exit 1
|
||||
fi
|
||||
PROTOC_OS="$(uname -s)"
|
||||
PROTOC_ARCH="$(uname -m)"
|
||||
case "${PROTOC_OS}" in
|
||||
Darwin) PROTOC_OS="osx" ;;
|
||||
Linux) PROTOC_OS="linux" ;;
|
||||
*)
|
||||
echo "Invalid value for uname -s: ${PROTOC_OS}" >&2
|
||||
exit 1
|
||||
esac
|
||||
|
||||
# This is for macs with M1 chips. Precompiled binaries for osx/amd64 are not available for download, so for that case
|
||||
# we download the x86_64 version instead. This will work as long as rosetta2 is installed.
|
||||
if [ "$PROTOC_OS" = "osx" ] && [ "$PROTOC_ARCH" = "arm64" ]; then
|
||||
PROTOC_ARCH="x86_64"
|
||||
fi
|
||||
|
||||
PROTOC="${PWD}/.tmp/protoc/bin/protoc"
|
||||
|
||||
if [[ "$(${PROTOC} --version 2>/dev/null)" != "libprotoc 3.${PROTOC_VERSION}" ]]; then
|
||||
rm -rf ./.tmp/protoc
|
||||
mkdir -p .tmp/protoc
|
||||
curl -L "https://github.com/google/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${PROTOC_OS}-${PROTOC_ARCH}.zip" > .tmp/protoc/protoc.zip
|
||||
pushd ./.tmp/protoc && unzip protoc.zip && popd
|
||||
fi
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"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 we have to import this because it appears in exported API
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/dynamic"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -136,10 +136,25 @@ type Formatter func(proto.Message) (string, error)
|
||||
func NewJSONFormatter(emitDefaults bool, resolver jsonpb.AnyResolver) Formatter {
|
||||
marshaler := jsonpb.Marshaler{
|
||||
EmitDefaults: emitDefaults,
|
||||
Indent: " ",
|
||||
AnyResolver: resolver,
|
||||
}
|
||||
return marshaler.MarshalToString
|
||||
// Workaround for indentation issue in jsonpb with Any messages.
|
||||
// Bug was originally fixed in https://github.com/golang/protobuf/pull/834
|
||||
// but later re-introduced before the module was deprecated and frozen.
|
||||
// If jsonpb is ever replaced with google.golang.org/protobuf/encoding/protojson
|
||||
// this workaround will no longer be needed.
|
||||
formatter := func(message proto.Message) (string, error) {
|
||||
output, err := marshaler.MarshalToString(message)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := json.Indent(&buf, []byte(output), "", " "); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
return formatter
|
||||
}
|
||||
|
||||
// NewTextFormatter returns a formatter that returns strings in the protobuf
|
||||
@@ -197,10 +212,20 @@ func (tf *textFormatter) format(m proto.Message) (string, error) {
|
||||
return str, nil
|
||||
}
|
||||
|
||||
// Format of request data. The allowed values are 'json' or 'text'.
|
||||
type Format string
|
||||
|
||||
const (
|
||||
// FormatJSON specifies input data in JSON format. Multiple request values
|
||||
// may be concatenated (messages with a JSON representation other than
|
||||
// object must be separated by whitespace, such as a newline)
|
||||
FormatJSON = Format("json")
|
||||
|
||||
// FormatText specifies input data must be in the protobuf text format.
|
||||
// Multiple request values must be separated by the "record separator"
|
||||
// ASCII character: 0x1E. The stream should not end in a record separator.
|
||||
// If it does, it will be interpreted as a final, blank message after the
|
||||
// separator.
|
||||
FormatText = Format("text")
|
||||
)
|
||||
|
||||
@@ -264,11 +289,11 @@ func (r *anyResolver) Resolve(typeUrl string) (proto.Message, error) {
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown message: %s", typeUrl)
|
||||
}
|
||||
// populate any extensions for this message, too
|
||||
if exts, err := r.source.AllExtensionsForType(mname); err != nil {
|
||||
return nil, err
|
||||
} else if err := r.er.AddExtension(exts...); err != nil {
|
||||
return nil, err
|
||||
// populate any extensions for this message, too (if there are any)
|
||||
if exts, err := r.source.AllExtensionsForType(mname); err == nil {
|
||||
if err := r.er.AddExtension(exts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if r.mf == nil {
|
||||
@@ -305,7 +330,6 @@ func (r anyResolverWithFallback) Resolve(typeUrl string) (proto.Message, error)
|
||||
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
|
||||
mname = mname[slash+1:]
|
||||
}
|
||||
//lint:ignore SA1019 new non-deprecated API requires other code changes; deferring...
|
||||
mt := proto.MessageType(mname)
|
||||
if mt != nil {
|
||||
return reflect.New(mt.Elem()).Interface().(proto.Message), nil
|
||||
@@ -428,7 +452,7 @@ type DefaultEventHandler struct {
|
||||
// the given output. If verbose is true, all events are logged. Otherwise, only
|
||||
// response messages are logged.
|
||||
//
|
||||
// Deprecated: NewDefaultEventHandler exists for compatability.
|
||||
// Deprecated: NewDefaultEventHandler exists for compatibility.
|
||||
// It doesn't allow fine control over the `VerbosityLevel`
|
||||
// and provides only 0 and 1 options (which corresponds to the `verbose` argument).
|
||||
// Use DefaultEventHandler{} initializer directly.
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"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 we have to import this because it appears in exported API
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
@@ -1,14 +1,44 @@
|
||||
module github.com/fullstorydev/grpcurl
|
||||
|
||||
go 1.15
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.56.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/golang/protobuf v1.4.2
|
||||
github.com/jhump/protoreflect v1.10.1
|
||||
google.golang.org/grpc v1.37.0
|
||||
google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/jhump/protoreflect v1.18.1
|
||||
google.golang.org/grpc v1.83.2
|
||||
google.golang.org/protobuf v1.36.12
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.25.2 // indirect
|
||||
cloud.google.com/go/auth v0.18.2 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.17.0 // 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
|
||||
github.com/spiffe/go-spiffe/v2 v2.7.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.44.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.44.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.44.0 // indirect
|
||||
golang.org/x/crypto v0.55.0 // indirect
|
||||
golang.org/x/net v0.58.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sync v0.22.0 // indirect
|
||||
golang.org/x/sys v0.47.0 // indirect
|
||||
golang.org/x/text v0.41.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
)
|
||||
|
||||
@@ -1,327 +1,95 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4=
|
||||
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/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
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 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs=
|
||||
cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
|
||||
cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
|
||||
cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=
|
||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
|
||||
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
|
||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4=
|
||||
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/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 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
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 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/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/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.1 h1:iH+UZfsbRE6vpyZH7asAjTPWJf7RJbpZ9j/N3lDlKs0=
|
||||
github.com/jhump/protoreflect v1.10.1/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/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA=
|
||||
github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A=
|
||||
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
|
||||
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
|
||||
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8=
|
||||
github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc=
|
||||
github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY=
|
||||
github.com/jhump/protoreflect v1.18.1 h1:h4odAaLg9wyn7yHxMF7sSkJ7JfLwK1oy37/1Pi212GE=
|
||||
github.com/jhump/protoreflect v1.18.1/go.mod h1:I2yar2oJEMf0k4EMryPzfV0tvGwN/SejJziYBOpETQo=
|
||||
github.com/jhump/protoreflect/v2 v2.0.0-beta.1 h1:Dw1rslK/VotaUGYsv53XVWITr+5RCPXfvvlGrM/+B6w=
|
||||
github.com/jhump/protoreflect/v2 v2.0.0-beta.1/go.mod h1:D9LBEowZyv8/iSu97FU2zmXG3JxVTmNw21mu63niFzU=
|
||||
github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741 h1:KPpdlQLZcHfTMQRi6bFQ7ogNO0ltFT4PmtwTLW4W+14=
|
||||
github.com/petermattis/goid v0.0.0-20260113132338-7c7de50cc741/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.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-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.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
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 h1:OwhZOOMuf7leLaSCuxtQ9FW7ui2L2L6UKOtKAUqovUQ=
|
||||
google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
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.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-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=
|
||||
github.com/spiffe/go-spiffe/v2 v2.7.0 h1:uXe1MflJoHw58wAUvxVlcM7WpKtijWG7I1UidcGh6g4=
|
||||
github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
|
||||
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
|
||||
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
|
||||
go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
|
||||
go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
|
||||
go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
|
||||
go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=
|
||||
go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=
|
||||
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
|
||||
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
|
||||
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
|
||||
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
||||
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU=
|
||||
google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
+169
-60
@@ -14,19 +14,25 @@ import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/desc/protoprint"
|
||||
"github.com/jhump/protoreflect/dynamic"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
xdsCredentials "google.golang.org/grpc/credentials/xds"
|
||||
_ "google.golang.org/grpc/health" // import grpc/health to enable transparent client side checking
|
||||
"google.golang.org/grpc/metadata"
|
||||
protov2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
@@ -328,7 +334,7 @@ func fetchAllExtensions(source DescriptorSource, ext *dynamic.ExtensionRegistry,
|
||||
return nil
|
||||
}
|
||||
|
||||
// fullConvertToDynamic attempts to convert the given message to a dynamic message as well
|
||||
// fullyConvertToDynamic attempts to convert the given message to a dynamic message as well
|
||||
// as any nested messages it may contain as field values. If the given message factory has
|
||||
// extensions registered that were not known when the given message was parsed, this effectively
|
||||
// allows re-parsing to identify those extensions.
|
||||
@@ -406,9 +412,9 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
|
||||
case "google.protobuf.Any":
|
||||
// empty type URL is not allowed by JSON representation
|
||||
// so we must give it a dummy type
|
||||
var any anypb.Any
|
||||
_ = anypb.MarshalFrom(&any, &emptypb.Empty{}, protov2.MarshalOptions{})
|
||||
return &any
|
||||
var anyVal anypb.Any
|
||||
_ = anypb.MarshalFrom(&anyVal, &emptypb.Empty{}, protov2.MarshalOptions{})
|
||||
return &anyVal
|
||||
case "google.protobuf.Value":
|
||||
// unset kind is not allowed by JSON representation
|
||||
// so we must give it something
|
||||
@@ -448,11 +454,9 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
|
||||
dm := dynamic.NewMessage(md)
|
||||
|
||||
// if the message is a recursive structure, we don't want to blow the stack
|
||||
for _, seen := range path {
|
||||
if seen == md {
|
||||
// already visited this type; avoid infinite recursion
|
||||
return dm
|
||||
}
|
||||
if slices.Contains(path, md) {
|
||||
// already visited this type; avoid infinite recursion
|
||||
return dm
|
||||
}
|
||||
path = append(path, dm.GetMessageDescriptor())
|
||||
|
||||
@@ -543,7 +547,7 @@ func ClientTLSConfig(insecureSkipVerify bool, cacertFile, clientCertFile, client
|
||||
} else if cacertFile != "" {
|
||||
// Create a certificate pool from the certificate authority
|
||||
certPool := x509.NewCertPool()
|
||||
ca, err := ioutil.ReadFile(cacertFile)
|
||||
ca, err := os.ReadFile(cacertFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read ca certificate: %v", err)
|
||||
}
|
||||
@@ -566,9 +570,6 @@ func ClientTLSConfig(insecureSkipVerify bool, cacertFile, clientCertFile, client
|
||||
// client certs. The serverCertFile and serverKeyFile must both not be blank.
|
||||
func ServerTransportCredentials(cacertFile, serverCertFile, serverKeyFile string, requireClientCerts bool) (credentials.TransportCredentials, error) {
|
||||
var tlsConf tls.Config
|
||||
// TODO(jh): Remove this line once https://github.com/golang/go/issues/28779 is fixed
|
||||
// in Go tip. Until then, the recently merged TLS 1.3 support breaks the TLS tests.
|
||||
tlsConf.MaxVersion = tls.VersionTLS12
|
||||
|
||||
// Load the server certificates from disk
|
||||
certificate, err := tls.LoadX509KeyPair(serverCertFile, serverKeyFile)
|
||||
@@ -580,7 +581,7 @@ func ServerTransportCredentials(cacertFile, serverCertFile, serverKeyFile string
|
||||
if cacertFile != "" {
|
||||
// Create a certificate pool from the certificate authority
|
||||
certPool := x509.NewCertPool()
|
||||
ca, err := ioutil.ReadFile(cacertFile)
|
||||
ca, err := os.ReadFile(cacertFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read ca certificate: %v", err)
|
||||
}
|
||||
@@ -607,13 +608,39 @@ func ServerTransportCredentials(cacertFile, serverCertFile, serverKeyFile string
|
||||
// BlockingDial is a helper method to dial the given address, using optional TLS credentials,
|
||||
// and blocking until the returned connection is ready. If the given credentials are nil, the
|
||||
// connection will be insecure (plain-text).
|
||||
// The network parameter should be left empty in most cases when your address is a RFC 3986
|
||||
// compliant URI. The resolver from grpc-go will resolve the correct network type.
|
||||
func BlockingDial(ctx context.Context, network, address string, creds credentials.TransportCredentials, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
|
||||
if creds == nil {
|
||||
creds = insecure.NewCredentials()
|
||||
}
|
||||
|
||||
var err error
|
||||
if strings.HasPrefix(address, "xds://") {
|
||||
// The xds:// prefix is used to signal to the gRPC client to use an xDS server to resolve the
|
||||
// target. The relevant credentials will be automatically pulled from the GRPC_XDS_BOOTSTRAP or
|
||||
// GRPC_XDS_BOOTSTRAP_CONFIG env vars.
|
||||
creds, err = xdsCredentials.NewClientCredentials(xdsCredentials.ClientOptions{FallbackCreds: creds})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// grpc.Dial doesn't provide any information on permanent connection errors (like
|
||||
// TLS handshake failures). So in order to provide good error messages, we need a
|
||||
// custom dialer that can provide that info. That means we manage the TLS handshake.
|
||||
result := make(chan interface{}, 1)
|
||||
|
||||
// dialCompleted is closed once the outcome of the dial (ready connection
|
||||
// or error) is known, so that connection teardown no longer needs to wait
|
||||
// for a pending TLS alert to be read.
|
||||
dialCompleted := make(chan struct{})
|
||||
var dialCompletedOnce sync.Once
|
||||
completeDial := func() { dialCompletedOnce.Do(func() { close(dialCompleted) }) }
|
||||
defer completeDial()
|
||||
|
||||
writeResult := func(res interface{}) {
|
||||
completeDial()
|
||||
// non-blocking write: we only need the first result
|
||||
select {
|
||||
case result <- res:
|
||||
@@ -623,52 +650,75 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
|
||||
|
||||
// custom credentials and dialer will notify on error via the
|
||||
// writeResult function
|
||||
if creds != nil {
|
||||
creds = &errSignalingCreds{
|
||||
TransportCredentials: creds,
|
||||
writeResult: writeResult,
|
||||
}
|
||||
}
|
||||
dialer := func(ctx context.Context, address string) (net.Conn, error) {
|
||||
// NB: We *could* handle the TLS handshake ourselves, in the custom
|
||||
// dialer (instead of customizing both the dialer and the credentials).
|
||||
// But that requires using WithInsecure dial option (so that the gRPC
|
||||
// library doesn't *also* try to do a handshake). And that would mean
|
||||
// that the library would send the wrong ":scheme" metaheader to
|
||||
// servers: it would send "http" instead of "https" because it is
|
||||
// unaware that TLS is actually in use.
|
||||
conn, err := (&net.Dialer{}).DialContext(ctx, network, address)
|
||||
if err != nil {
|
||||
writeResult(err)
|
||||
}
|
||||
return conn, err
|
||||
creds = &errSignalingCreds{
|
||||
TransportCredentials: creds,
|
||||
writeResult: writeResult,
|
||||
dialCompleted: dialCompleted,
|
||||
}
|
||||
|
||||
// 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
|
||||
// know when we're done. So we run it in a goroutine and then use result
|
||||
// channel to either get the connection or fail-fast.
|
||||
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) {
|
||||
conn, err := (&net.Dialer{}).DialContext(ctx, network, address)
|
||||
if err != nil {
|
||||
// capture the error so we can provide a better message
|
||||
writeResult(err)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
opts = append([]grpc.DialOption{grpc.WithContextDialer(dialer)}, opts...)
|
||||
}
|
||||
|
||||
// grpc.NewClient does not connect immediately, so we use conn.Connect()
|
||||
// to trigger eager connection and then poll connectivity state to block
|
||||
// until ready. The errSignalingCreds wrapper will capture TLS handshake
|
||||
// errors and write them to the result channel for fail-fast behavior.
|
||||
|
||||
// Normalize address for NewClient which defaults to "dns" resolver.
|
||||
// Bare host:port addresses need "passthrough:///" to preserve the old
|
||||
// grpc.Dial behavior.
|
||||
if !strings.Contains(address, "://") {
|
||||
address = "passthrough:///" + address
|
||||
}
|
||||
|
||||
opts = append(opts, grpc.WithTransportCredentials(creds))
|
||||
|
||||
conn, err := grpc.NewClient(address, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn.Connect()
|
||||
|
||||
go func() {
|
||||
// We put grpc.FailOnNonTempDialError *before* the explicitly provided
|
||||
// options so that it could be overridden.
|
||||
opts = append([]grpc.DialOption{grpc.FailOnNonTempDialError(true)}, opts...)
|
||||
// But we don't want caller to be able to override these two, so we put
|
||||
// them *after* the explicitly provided options.
|
||||
opts = append(opts, grpc.WithBlock(), grpc.WithContextDialer(dialer))
|
||||
|
||||
if creds == nil {
|
||||
opts = append(opts, grpc.WithInsecure())
|
||||
} else {
|
||||
opts = append(opts, grpc.WithTransportCredentials(creds))
|
||||
for {
|
||||
s := conn.GetState()
|
||||
if s == connectivity.Ready {
|
||||
writeResult(conn)
|
||||
return
|
||||
}
|
||||
if s == connectivity.Shutdown {
|
||||
return
|
||||
}
|
||||
if !conn.WaitForStateChange(ctx, s) {
|
||||
// Context expired
|
||||
return
|
||||
}
|
||||
}
|
||||
conn, err := grpc.DialContext(ctx, address, opts...)
|
||||
var res interface{}
|
||||
if err != nil {
|
||||
res = err
|
||||
} else {
|
||||
res = conn
|
||||
}
|
||||
writeResult(res)
|
||||
}()
|
||||
|
||||
select {
|
||||
@@ -686,13 +736,72 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
|
||||
// it will use the writeResult function to notify on error.
|
||||
type errSignalingCreds struct {
|
||||
credentials.TransportCredentials
|
||||
writeResult func(res interface{})
|
||||
writeResult func(res interface{})
|
||||
dialCompleted <-chan struct{}
|
||||
}
|
||||
|
||||
func (c *errSignalingCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
|
||||
conn, auth, err := c.TransportCredentials.ClientHandshake(ctx, addr, rawConn)
|
||||
if err != nil {
|
||||
c.writeResult(err)
|
||||
return conn, auth, err
|
||||
}
|
||||
return conn, auth, err
|
||||
// Wrap the connection to capture post-handshake errors, e.g.:
|
||||
// - TLS 1.3 client cert rejection (server sends alert after handshake)
|
||||
// - Plaintext client to TLS server (server closes conn immediately)
|
||||
return &errSignalingConn{Conn: conn, writeResult: c.writeResult, dialCompleted: c.dialCompleted}, auth, nil
|
||||
}
|
||||
|
||||
// maxTLSAlertWait is an upper bound on how long a failing dial's connection
|
||||
// teardown waits for a pending TLS alert to be read. It is a heuristic: long
|
||||
// enough for the reader goroutine to be scheduled even on a loaded machine,
|
||||
// short enough to not noticeably delay a failing dial.
|
||||
const maxTLSAlertWait = 50 * time.Millisecond
|
||||
|
||||
// errSignalingConn wraps a net.Conn to capture read errors and report
|
||||
// them via writeResult. Close is delayed until the dial has completed to
|
||||
// give the reader a chance to read a pending TLS alert before the
|
||||
// connection is closed.
|
||||
type errSignalingConn struct {
|
||||
net.Conn
|
||||
writeResult func(res interface{})
|
||||
dialCompleted <-chan struct{}
|
||||
}
|
||||
|
||||
func (c *errSignalingConn) Read(b []byte) (int, error) {
|
||||
n, err := c.Conn.Read(b)
|
||||
if err != nil {
|
||||
c.writeResult(err)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (c *errSignalingConn) Close() error {
|
||||
// With TLS 1.3, the server may reject the connection *after* the
|
||||
// handshake completes (e.g. a missing client cert), by sending an alert.
|
||||
// If the transport closes the connection before that alert is read, the
|
||||
// caller sees a less useful error (e.g. "use of closed network
|
||||
// connection") instead of the TLS alert. So while the outcome of the
|
||||
// dial is still undecided, give the reader a brief window to read a
|
||||
// pending alert before closing the connection.
|
||||
select {
|
||||
case <-c.dialCompleted:
|
||||
case <-time.After(maxTLSAlertWait):
|
||||
}
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
// UsesXDS forwards the optional UsesXDS marker of the wrapped credentials. The
|
||||
// xDS credentials returned for "xds://" targets implement this method, and
|
||||
// grpc-go's cds balancer relies on a type assertion for it to decide whether to
|
||||
// apply the security configuration (e.g. UpstreamTlsContext) delivered by the
|
||||
// management server. Because errSignalingCreds embeds the TransportCredentials
|
||||
// interface, that extra method is not promoted automatically, so we forward it
|
||||
// explicitly. Without this, xDS-supplied mTLS is silently ignored and the
|
||||
// connection falls back to the plain credentials.
|
||||
func (c *errSignalingCreds) UsesXDS() bool {
|
||||
if x, ok := c.TransportCredentials.(interface{ UsesXDS() bool }); ok {
|
||||
return x.UsesXDS()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+16
-30
@@ -12,15 +12,15 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"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 we have to import this because it appears in exported API
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/grpcreflect"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/reflection"
|
||||
reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
. "github.com/fullstorydev/grpcurl"
|
||||
@@ -74,14 +74,12 @@ func TestMain(m *testing.M) {
|
||||
defer svrReflect.Stop()
|
||||
|
||||
// And a corresponding client
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
if ccReflect, err = grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%d", portReflect),
|
||||
grpc.WithInsecure(), grpc.WithBlock()); err != nil {
|
||||
if ccReflect, err = grpc.NewClient(fmt.Sprintf("passthrough:///127.0.0.1:%d", portReflect),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials())); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer ccReflect.Close()
|
||||
refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(ccReflect))
|
||||
refClient := grpcreflect.NewClientAuto(context.Background(), ccReflect)
|
||||
defer refClient.Reset()
|
||||
|
||||
sourceReflect = DescriptorSourceFromServer(context.Background(), refClient)
|
||||
@@ -99,10 +97,8 @@ func TestMain(m *testing.M) {
|
||||
defer svrProtoset.Stop()
|
||||
|
||||
// And a corresponding client
|
||||
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
if ccNoReflect, err = grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%d", portProtoset),
|
||||
grpc.WithInsecure(), grpc.WithBlock()); err != nil {
|
||||
if ccNoReflect, err = grpc.NewClient(fmt.Sprintf("passthrough:///127.0.0.1:%d", portProtoset),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials())); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer ccNoReflect.Close()
|
||||
@@ -117,7 +113,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func TestServerDoesNotSupportReflection(t *testing.T) {
|
||||
refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(ccNoReflect))
|
||||
refClient := grpcreflect.NewClientAuto(context.Background(), ccNoReflect)
|
||||
defer refClient.Reset()
|
||||
|
||||
refSource := DescriptorSourceFromServer(context.Background(), refClient)
|
||||
@@ -177,7 +173,7 @@ func doTestListServices(t *testing.T, source DescriptorSource, includeReflection
|
||||
var expected []string
|
||||
if includeReflection {
|
||||
// when using server reflection, we see the TestService as well as the ServerReflection service
|
||||
expected = []string{"grpc.reflection.v1alpha.ServerReflection", "testing.TestService"}
|
||||
expected = []string{"grpc.reflection.v1.ServerReflection", "grpc.reflection.v1alpha.ServerReflection", "testing.TestService"}
|
||||
} else {
|
||||
// without reflection, we see all services defined in the same test.proto file, which is the
|
||||
// TestService as well as UnimplementedService
|
||||
@@ -215,11 +211,11 @@ func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection
|
||||
|
||||
if includeReflection {
|
||||
// when using server reflection, we see the TestService as well as the ServerReflection service
|
||||
names, err = ListMethods(source, "grpc.reflection.v1alpha.ServerReflection")
|
||||
names, err = ListMethods(source, "grpc.reflection.v1.ServerReflection")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list methods for ServerReflection: %v", err)
|
||||
}
|
||||
expected = []string{"grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo"}
|
||||
expected = []string{"grpc.reflection.v1.ServerReflection.ServerReflectionInfo"}
|
||||
} else {
|
||||
// without reflection, we see all services defined in the same test.proto file, which is the
|
||||
// TestService as well as UnimplementedService
|
||||
@@ -242,12 +238,8 @@ func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection
|
||||
|
||||
func TestGetAllFiles(t *testing.T) {
|
||||
expectedFiles := []string{"test.proto"}
|
||||
// server reflection picks up filename from linked in Go package,
|
||||
// which indicates "grpc_testing/test.proto", not our local copy.
|
||||
expectedFilesWithReflection := [][]string{
|
||||
{"grpc_reflection_v1alpha/reflection.proto", "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"},
|
||||
expectedFilesWithReflection := []string{
|
||||
"grpc/reflection/v1/reflection.proto", "grpc/reflection/v1alpha/reflection.proto", "test.proto",
|
||||
}
|
||||
|
||||
for _, ds := range descSources {
|
||||
@@ -260,17 +252,11 @@ func TestGetAllFiles(t *testing.T) {
|
||||
match := false
|
||||
var expected []string
|
||||
if ds.includeRefl {
|
||||
for _, expectedNames := range expectedFilesWithReflection {
|
||||
expected = expectedNames
|
||||
if reflect.DeepEqual(expected, names) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
expected = expectedFilesWithReflection
|
||||
} else {
|
||||
expected = expectedFiles
|
||||
match = reflect.DeepEqual(expected, names)
|
||||
}
|
||||
match = reflect.DeepEqual(expected, names)
|
||||
if !match {
|
||||
t.Errorf("GetAllFiles returned wrong results: wanted %v, got %v", expected, names)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
|
||||
// bankServer implements the Bank gRPC service.
|
||||
type bankServer struct {
|
||||
UnimplementedBankServer
|
||||
allAccounts *accounts
|
||||
}
|
||||
|
||||
@@ -72,26 +72,29 @@ func (s *bankServer) GetTransactions(req *GetTransactionsRequest, stream Bank_Ge
|
||||
|
||||
var start, end time.Time
|
||||
if req.Start != nil {
|
||||
start, err = ptypes.Timestamp(req.Start)
|
||||
err := req.Start.CheckValid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
start = req.Start.AsTime()
|
||||
}
|
||||
if req.End != nil {
|
||||
end, err = ptypes.Timestamp(req.End)
|
||||
err := req.End.CheckValid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
end = req.End.AsTime()
|
||||
} else {
|
||||
end = time.Date(9999, 12, 31, 23, 59, 59, 999999999, time.Local)
|
||||
}
|
||||
|
||||
txns := acct.getTransactions()
|
||||
for _, txn := range txns {
|
||||
t, err := ptypes.Timestamp(txn.Date)
|
||||
err := txn.Date.CheckValid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t := txn.Date.AsTime()
|
||||
if (t.After(start) || t.Equal(start)) &&
|
||||
(t.Before(end) || t.Equal(end)) {
|
||||
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0-devel
|
||||
// protoc v3.14.0
|
||||
// protoc v4.22.0
|
||||
// source: bank.proto
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
context "context"
|
||||
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"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
@@ -696,10 +692,12 @@ type TransferRequest struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Source:
|
||||
//
|
||||
// *TransferRequest_SourceAccountNumber
|
||||
// *TransferRequest_ExternalSource
|
||||
Source isTransferRequest_Source `protobuf_oneof:"source"`
|
||||
// Types that are assignable to Dest:
|
||||
//
|
||||
// *TransferRequest_DestAccountNumber
|
||||
// *TransferRequest_ExternalDest
|
||||
Dest isTransferRequest_Dest `protobuf_oneof:"dest"`
|
||||
@@ -1347,355 +1345,3 @@ func file_bank_proto_init() {
|
||||
file_bank_proto_goTypes = 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",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// BankClient is the client API for Bank service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type BankClient interface {
|
||||
// OpenAccount creates an account with the type and given initial deposit
|
||||
// as its balance.
|
||||
OpenAccount(ctx context.Context, in *OpenAccountRequest, opts ...grpc.CallOption) (*Account, error)
|
||||
// CloseAccount closes the indicated account. An account can only be
|
||||
// closed if its balance is zero.
|
||||
CloseAccount(ctx context.Context, in *CloseAccountRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// GetAccounts lists all accounts for the current customer.
|
||||
GetAccounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetAccountsResponse, error)
|
||||
// GetTransactions streams all transactions that match the given criteria.
|
||||
// If the given start date is not specified, transactions since beginning
|
||||
// of time are included. Similarly, if the given end date is not specified,
|
||||
// transactions all the way to the presnet are included.
|
||||
GetTransactions(ctx context.Context, in *GetTransactionsRequest, opts ...grpc.CallOption) (Bank_GetTransactionsClient, error)
|
||||
// Deposit increases the balance of an account by depositing funds into it.
|
||||
Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*BalanceResponse, error)
|
||||
// Withdraw decreases the balance of an account by withdrawing funds from it.
|
||||
Withdraw(ctx context.Context, in *WithdrawRequest, opts ...grpc.CallOption) (*BalanceResponse, error)
|
||||
// Transfer moves money from one account to another. The source and destination
|
||||
// accounts can be with this bank (e.g. "local" account numbers) or can be
|
||||
// external accounts, identified by their ACH routing and account numbers.
|
||||
Transfer(ctx context.Context, in *TransferRequest, opts ...grpc.CallOption) (*TransferResponse, error)
|
||||
}
|
||||
|
||||
type bankClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewBankClient(cc grpc.ClientConnInterface) BankClient {
|
||||
return &bankClient{cc}
|
||||
}
|
||||
|
||||
func (c *bankClient) OpenAccount(ctx context.Context, in *OpenAccountRequest, opts ...grpc.CallOption) (*Account, error) {
|
||||
out := new(Account)
|
||||
err := c.cc.Invoke(ctx, "/Bank/OpenAccount", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) CloseAccount(ctx context.Context, in *CloseAccountRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/Bank/CloseAccount", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) GetAccounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetAccountsResponse, error) {
|
||||
out := new(GetAccountsResponse)
|
||||
err := c.cc.Invoke(ctx, "/Bank/GetAccounts", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) GetTransactions(ctx context.Context, in *GetTransactionsRequest, opts ...grpc.CallOption) (Bank_GetTransactionsClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Bank_ServiceDesc.Streams[0], "/Bank/GetTransactions", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &bankGetTransactionsClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Bank_GetTransactionsClient interface {
|
||||
Recv() (*Transaction, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type bankGetTransactionsClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *bankGetTransactionsClient) Recv() (*Transaction, error) {
|
||||
m := new(Transaction)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*BalanceResponse, error) {
|
||||
out := new(BalanceResponse)
|
||||
err := c.cc.Invoke(ctx, "/Bank/Deposit", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) Withdraw(ctx context.Context, in *WithdrawRequest, opts ...grpc.CallOption) (*BalanceResponse, error) {
|
||||
out := new(BalanceResponse)
|
||||
err := c.cc.Invoke(ctx, "/Bank/Withdraw", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *bankClient) Transfer(ctx context.Context, in *TransferRequest, opts ...grpc.CallOption) (*TransferResponse, error) {
|
||||
out := new(TransferResponse)
|
||||
err := c.cc.Invoke(ctx, "/Bank/Transfer", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// BankServer is the server API for Bank service.
|
||||
// All implementations must embed UnimplementedBankServer
|
||||
// for forward compatibility
|
||||
type BankServer interface {
|
||||
// OpenAccount creates an account with the type and given initial deposit
|
||||
// as its balance.
|
||||
OpenAccount(context.Context, *OpenAccountRequest) (*Account, error)
|
||||
// CloseAccount closes the indicated account. An account can only be
|
||||
// closed if its balance is zero.
|
||||
CloseAccount(context.Context, *CloseAccountRequest) (*emptypb.Empty, error)
|
||||
// GetAccounts lists all accounts for the current customer.
|
||||
GetAccounts(context.Context, *emptypb.Empty) (*GetAccountsResponse, error)
|
||||
// GetTransactions streams all transactions that match the given criteria.
|
||||
// If the given start date is not specified, transactions since beginning
|
||||
// of time are included. Similarly, if the given end date is not specified,
|
||||
// transactions all the way to the presnet are included.
|
||||
GetTransactions(*GetTransactionsRequest, Bank_GetTransactionsServer) error
|
||||
// Deposit increases the balance of an account by depositing funds into it.
|
||||
Deposit(context.Context, *DepositRequest) (*BalanceResponse, error)
|
||||
// Withdraw decreases the balance of an account by withdrawing funds from it.
|
||||
Withdraw(context.Context, *WithdrawRequest) (*BalanceResponse, error)
|
||||
// Transfer moves money from one account to another. The source and destination
|
||||
// accounts can be with this bank (e.g. "local" account numbers) or can be
|
||||
// external accounts, identified by their ACH routing and account numbers.
|
||||
Transfer(context.Context, *TransferRequest) (*TransferResponse, error)
|
||||
mustEmbedUnimplementedBankServer()
|
||||
}
|
||||
|
||||
// UnimplementedBankServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedBankServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedBankServer) OpenAccount(context.Context, *OpenAccountRequest) (*Account, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OpenAccount not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) CloseAccount(context.Context, *CloseAccountRequest) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CloseAccount not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) GetAccounts(context.Context, *emptypb.Empty) (*GetAccountsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAccounts not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) GetTransactions(*GetTransactionsRequest, Bank_GetTransactionsServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method GetTransactions not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) Deposit(context.Context, *DepositRequest) (*BalanceResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Deposit not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) Withdraw(context.Context, *WithdrawRequest) (*BalanceResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Withdraw not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) Transfer(context.Context, *TransferRequest) (*TransferResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Transfer not implemented")
|
||||
}
|
||||
func (UnimplementedBankServer) mustEmbedUnimplementedBankServer() {}
|
||||
|
||||
// UnsafeBankServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to BankServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeBankServer interface {
|
||||
mustEmbedUnimplementedBankServer()
|
||||
}
|
||||
|
||||
func RegisterBankServer(s grpc.ServiceRegistrar, srv BankServer) {
|
||||
s.RegisterService(&Bank_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Bank_OpenAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OpenAccountRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).OpenAccount(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/OpenAccount",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).OpenAccount(ctx, req.(*OpenAccountRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_CloseAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CloseAccountRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).CloseAccount(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/CloseAccount",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).CloseAccount(ctx, req.(*CloseAccountRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_GetAccounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(emptypb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).GetAccounts(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/GetAccounts",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).GetAccounts(ctx, req.(*emptypb.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_GetTransactions_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(GetTransactionsRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(BankServer).GetTransactions(m, &bankGetTransactionsServer{stream})
|
||||
}
|
||||
|
||||
type Bank_GetTransactionsServer interface {
|
||||
Send(*Transaction) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type bankGetTransactionsServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *bankGetTransactionsServer) Send(m *Transaction) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _Bank_Deposit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DepositRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).Deposit(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/Deposit",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).Deposit(ctx, req.(*DepositRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_Withdraw_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(WithdrawRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).Withdraw(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/Withdraw",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).Withdraw(ctx, req.(*WithdrawRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Bank_Transfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TransferRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BankServer).Transfer(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Bank/Transfer",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BankServer).Transfer(ctx, req.(*TransferRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Bank_ServiceDesc is the grpc.ServiceDesc for Bank service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Bank_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Bank",
|
||||
HandlerType: (*BankServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "OpenAccount",
|
||||
Handler: _Bank_OpenAccount_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CloseAccount",
|
||||
Handler: _Bank_CloseAccount_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetAccounts",
|
||||
Handler: _Bank_GetAccounts_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Deposit",
|
||||
Handler: _Bank_Deposit_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Withdraw",
|
||||
Handler: _Bank_Withdraw_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Transfer",
|
||||
Handler: _Bank_Transfer_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "GetTransactions",
|
||||
Handler: _Bank_GetTransactions_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "bank.proto",
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
// a capability to connect customers and support agents in real-time
|
||||
// chat.
|
||||
type chatServer struct {
|
||||
UnimplementedSupportServer
|
||||
chatsBySession map[string]*session
|
||||
chatsAwaitingAgent []string
|
||||
lastSession int32
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package main
|
||||
|
||||
//go:generate protoc --go_out=plugins=grpc:./ bank.proto support.proto
|
||||
//go:generate protoc --go_out=. --go-grpc_out=. bank.proto support.proto
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
@@ -130,7 +129,7 @@ type svr struct {
|
||||
}
|
||||
|
||||
func (s *svr) load() error {
|
||||
accts, err := ioutil.ReadFile(s.datafile)
|
||||
accts, err := os.ReadFile(s.datafile)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
@@ -162,7 +161,7 @@ func (s *svr) flush() {
|
||||
|
||||
if b, err := json.Marshal(accounts); err != nil {
|
||||
grpclog.Errorf("failed to save data to %q", s.datafile)
|
||||
} else if err := ioutil.WriteFile(s.datafile, b, 0666); err != nil {
|
||||
} else if err := os.WriteFile(s.datafile, b, 0666); err != nil {
|
||||
grpclog.Errorf("failed to save data to %q", s.datafile)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0-devel
|
||||
// protoc v3.14.0
|
||||
// protoc v4.22.0
|
||||
// source: support.proto
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
context "context"
|
||||
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"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
@@ -79,6 +75,7 @@ type ChatCustomerRequest struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Req:
|
||||
//
|
||||
// *ChatCustomerRequest_Init
|
||||
// *ChatCustomerRequest_Msg
|
||||
// *ChatCustomerRequest_HangUp
|
||||
@@ -286,6 +283,7 @@ type ChatCustomerResponse struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Resp:
|
||||
//
|
||||
// *ChatCustomerResponse_Session
|
||||
// *ChatCustomerResponse_Msg
|
||||
Resp isChatCustomerResponse_Resp `protobuf_oneof:"resp"`
|
||||
@@ -371,6 +369,7 @@ type ChatAgentRequest struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Req:
|
||||
//
|
||||
// *ChatAgentRequest_Accept
|
||||
// *ChatAgentRequest_Msg
|
||||
// *ChatAgentRequest_LeaveSession
|
||||
@@ -524,6 +523,7 @@ type ChatEntry struct {
|
||||
|
||||
Date *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty"`
|
||||
// Types that are assignable to Entry:
|
||||
//
|
||||
// *ChatEntry_CustomerMsg
|
||||
// *ChatEntry_AgentMsg
|
||||
Entry isChatEntry_Entry `protobuf_oneof:"entry"`
|
||||
@@ -611,6 +611,7 @@ type ChatAgentResponse struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Resp:
|
||||
//
|
||||
// *ChatAgentResponse_AcceptedSession
|
||||
// *ChatAgentResponse_Msg
|
||||
// *ChatAgentResponse_SessionEnded
|
||||
@@ -1056,199 +1057,3 @@ func file_support_proto_init() {
|
||||
file_support_proto_goTypes = 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",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// SupportClient is the client API for Support service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type SupportClient interface {
|
||||
// ChatCustomer is used by a customer-facing app to send the customer's messages
|
||||
// to a chat session. The customer is how initiates and terminates (via "hangup")
|
||||
// a chat session. Only customers may invoke this method (e.g. requests must
|
||||
// include customer auth credentials).
|
||||
ChatCustomer(ctx context.Context, opts ...grpc.CallOption) (Support_ChatCustomerClient, error)
|
||||
// ChatAgent is used by an agent-facing app to allow an agent to reply to a
|
||||
// customer's messages in a chat session. The agent may accept a chat session,
|
||||
// which defaults to the session awaiting an agent for the longest period of time
|
||||
// (FIFO queue).
|
||||
ChatAgent(ctx context.Context, opts ...grpc.CallOption) (Support_ChatAgentClient, error)
|
||||
}
|
||||
|
||||
type supportClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewSupportClient(cc grpc.ClientConnInterface) SupportClient {
|
||||
return &supportClient{cc}
|
||||
}
|
||||
|
||||
func (c *supportClient) ChatCustomer(ctx context.Context, opts ...grpc.CallOption) (Support_ChatCustomerClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Support_ServiceDesc.Streams[0], "/Support/ChatCustomer", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &supportChatCustomerClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Support_ChatCustomerClient interface {
|
||||
Send(*ChatCustomerRequest) error
|
||||
Recv() (*ChatCustomerResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type supportChatCustomerClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *supportChatCustomerClient) Send(m *ChatCustomerRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *supportChatCustomerClient) Recv() (*ChatCustomerResponse, error) {
|
||||
m := new(ChatCustomerResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *supportClient) ChatAgent(ctx context.Context, opts ...grpc.CallOption) (Support_ChatAgentClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Support_ServiceDesc.Streams[1], "/Support/ChatAgent", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &supportChatAgentClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Support_ChatAgentClient interface {
|
||||
Send(*ChatAgentRequest) error
|
||||
Recv() (*ChatAgentResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type supportChatAgentClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *supportChatAgentClient) Send(m *ChatAgentRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *supportChatAgentClient) Recv() (*ChatAgentResponse, error) {
|
||||
m := new(ChatAgentResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// SupportServer is the server API for Support service.
|
||||
// All implementations must embed UnimplementedSupportServer
|
||||
// for forward compatibility
|
||||
type SupportServer interface {
|
||||
// ChatCustomer is used by a customer-facing app to send the customer's messages
|
||||
// to a chat session. The customer is how initiates and terminates (via "hangup")
|
||||
// a chat session. Only customers may invoke this method (e.g. requests must
|
||||
// include customer auth credentials).
|
||||
ChatCustomer(Support_ChatCustomerServer) error
|
||||
// ChatAgent is used by an agent-facing app to allow an agent to reply to a
|
||||
// customer's messages in a chat session. The agent may accept a chat session,
|
||||
// which defaults to the session awaiting an agent for the longest period of time
|
||||
// (FIFO queue).
|
||||
ChatAgent(Support_ChatAgentServer) error
|
||||
mustEmbedUnimplementedSupportServer()
|
||||
}
|
||||
|
||||
// UnimplementedSupportServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedSupportServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedSupportServer) ChatCustomer(Support_ChatCustomerServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method ChatCustomer not implemented")
|
||||
}
|
||||
func (UnimplementedSupportServer) ChatAgent(Support_ChatAgentServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method ChatAgent not implemented")
|
||||
}
|
||||
func (UnimplementedSupportServer) mustEmbedUnimplementedSupportServer() {}
|
||||
|
||||
// UnsafeSupportServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to SupportServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeSupportServer interface {
|
||||
mustEmbedUnimplementedSupportServer()
|
||||
}
|
||||
|
||||
func RegisterSupportServer(s grpc.ServiceRegistrar, srv SupportServer) {
|
||||
s.RegisterService(&Support_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Support_ChatCustomer_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(SupportServer).ChatCustomer(&supportChatCustomerServer{stream})
|
||||
}
|
||||
|
||||
type Support_ChatCustomerServer interface {
|
||||
Send(*ChatCustomerResponse) error
|
||||
Recv() (*ChatCustomerRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type supportChatCustomerServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *supportChatCustomerServer) Send(m *ChatCustomerResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *supportChatCustomerServer) Recv() (*ChatCustomerRequest, error) {
|
||||
m := new(ChatCustomerRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _Support_ChatAgent_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(SupportServer).ChatAgent(&supportChatAgentServer{stream})
|
||||
}
|
||||
|
||||
type Support_ChatAgentServer interface {
|
||||
Send(*ChatAgentResponse) error
|
||||
Recv() (*ChatAgentRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type supportChatAgentServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *supportChatAgentServer) Send(m *ChatAgentResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *supportChatAgentServer) Recv() (*ChatAgentRequest, error) {
|
||||
m := new(ChatAgentRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Support_ServiceDesc is the grpc.ServiceDesc for Support service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Support_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Support",
|
||||
HandlerType: (*SupportServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "ChatCustomer",
|
||||
Handler: _Support_ChatCustomer_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "ChatAgent",
|
||||
Handler: _Support_ChatAgent_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "support.proto",
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
|
||||
package main
|
||||
|
||||
|
||||
Binary file not shown.
+1
-493
@@ -20,17 +20,13 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0-devel
|
||||
// protoc v3.14.0
|
||||
// protoc v4.22.0
|
||||
// source: test.proto
|
||||
|
||||
package testing
|
||||
|
||||
import (
|
||||
context "context"
|
||||
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"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
@@ -1032,491 +1028,3 @@ func file_test_proto_init() {
|
||||
file_test_proto_goTypes = 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",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,523 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package testing
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// TestServiceClient is the client API for TestService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type TestServiceClient interface {
|
||||
// One empty request followed by one empty response.
|
||||
EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
|
||||
// One request followed by one response.
|
||||
// The server returns the client payload as-is.
|
||||
UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error)
|
||||
// One request followed by a sequence of responses (streamed download).
|
||||
// The server returns the payload with client desired type and sizes.
|
||||
StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error)
|
||||
// A sequence of requests followed by one response (streamed upload).
|
||||
// The server returns the aggregated size of client payload as the result.
|
||||
StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error)
|
||||
// A sequence of requests with each request served by the server immediately.
|
||||
// As one request could lead to multiple responses, this interface
|
||||
// demonstrates the idea of full duplexing.
|
||||
FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error)
|
||||
// A sequence of requests followed by a sequence of responses.
|
||||
// The server buffers all the client requests and then serves them in order. A
|
||||
// stream of responses are returned to the client when the server starts with
|
||||
// first request.
|
||||
HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error)
|
||||
}
|
||||
|
||||
type testServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewTestServiceClient(cc grpc.ClientConnInterface) TestServiceClient {
|
||||
return &testServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *testServiceClient) EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
|
||||
out := new(Empty)
|
||||
err := c.cc.Invoke(ctx, "/testing.TestService/EmptyCall", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) {
|
||||
out := new(SimpleResponse)
|
||||
err := c.cc.Invoke(ctx, "/testing.TestService/UnaryCall", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[0], "/testing.TestService/StreamingOutputCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceStreamingOutputCallClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_StreamingOutputCallClient interface {
|
||||
Recv() (*StreamingOutputCallResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceStreamingOutputCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingOutputCallClient) Recv() (*StreamingOutputCallResponse, error) {
|
||||
m := new(StreamingOutputCallResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[1], "/testing.TestService/StreamingInputCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceStreamingInputCallClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_StreamingInputCallClient interface {
|
||||
Send(*StreamingInputCallRequest) error
|
||||
CloseAndRecv() (*StreamingInputCallResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceStreamingInputCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingInputCallClient) Send(m *StreamingInputCallRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingInputCallClient) CloseAndRecv() (*StreamingInputCallResponse, error) {
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := new(StreamingInputCallResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[2], "/testing.TestService/FullDuplexCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceFullDuplexCallClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_FullDuplexCallClient interface {
|
||||
Send(*StreamingOutputCallRequest) error
|
||||
Recv() (*StreamingOutputCallResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceFullDuplexCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
|
||||
m := new(StreamingOutputCallResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[3], "/testing.TestService/HalfDuplexCall", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServiceHalfDuplexCallClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_HalfDuplexCallClient interface {
|
||||
Send(*StreamingOutputCallRequest) error
|
||||
Recv() (*StreamingOutputCallResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServiceHalfDuplexCallClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServiceHalfDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
|
||||
m := new(StreamingOutputCallResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// TestServiceServer is the server API for TestService service.
|
||||
// All implementations must embed UnimplementedTestServiceServer
|
||||
// for forward compatibility
|
||||
type TestServiceServer interface {
|
||||
// One empty request followed by one empty response.
|
||||
EmptyCall(context.Context, *Empty) (*Empty, error)
|
||||
// One request followed by one response.
|
||||
// The server returns the client payload as-is.
|
||||
UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error)
|
||||
// One request followed by a sequence of responses (streamed download).
|
||||
// The server returns the payload with client desired type and sizes.
|
||||
StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error
|
||||
// A sequence of requests followed by one response (streamed upload).
|
||||
// The server returns the aggregated size of client payload as the result.
|
||||
StreamingInputCall(TestService_StreamingInputCallServer) error
|
||||
// A sequence of requests with each request served by the server immediately.
|
||||
// As one request could lead to multiple responses, this interface
|
||||
// demonstrates the idea of full duplexing.
|
||||
FullDuplexCall(TestService_FullDuplexCallServer) error
|
||||
// A sequence of requests followed by a sequence of responses.
|
||||
// The server buffers all the client requests and then serves them in order. A
|
||||
// stream of responses are returned to the client when the server starts with
|
||||
// first request.
|
||||
HalfDuplexCall(TestService_HalfDuplexCallServer) error
|
||||
mustEmbedUnimplementedTestServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedTestServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedTestServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedTestServiceServer) EmptyCall(context.Context, *Empty) (*Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method EmptyCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnaryCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method StreamingOutputCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) StreamingInputCall(TestService_StreamingInputCallServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method StreamingInputCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) FullDuplexCall(TestService_FullDuplexCallServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method FullDuplexCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) HalfDuplexCall(TestService_HalfDuplexCallServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method HalfDuplexCall not implemented")
|
||||
}
|
||||
func (UnimplementedTestServiceServer) mustEmbedUnimplementedTestServiceServer() {}
|
||||
|
||||
// UnsafeTestServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to TestServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeTestServiceServer interface {
|
||||
mustEmbedUnimplementedTestServiceServer()
|
||||
}
|
||||
|
||||
func RegisterTestServiceServer(s grpc.ServiceRegistrar, srv TestServiceServer) {
|
||||
s.RegisterService(&TestService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServiceServer).EmptyCall(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/testing.TestService/EmptyCall",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServiceServer).EmptyCall(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SimpleRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServiceServer).UnaryCall(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/testing.TestService/UnaryCall",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServiceServer).UnaryCall(ctx, req.(*SimpleRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TestService_StreamingOutputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(StreamingOutputCallRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(TestServiceServer).StreamingOutputCall(m, &testServiceStreamingOutputCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_StreamingOutputCallServer interface {
|
||||
Send(*StreamingOutputCallResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceStreamingOutputCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingOutputCallServer) Send(m *StreamingOutputCallResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _TestService_StreamingInputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).StreamingInputCall(&testServiceStreamingInputCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_StreamingInputCallServer interface {
|
||||
SendAndClose(*StreamingInputCallResponse) error
|
||||
Recv() (*StreamingInputCallRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceStreamingInputCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingInputCallServer) SendAndClose(m *StreamingInputCallResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceStreamingInputCallServer) Recv() (*StreamingInputCallRequest, error) {
|
||||
m := new(StreamingInputCallRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _TestService_FullDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).FullDuplexCall(&testServiceFullDuplexCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_FullDuplexCallServer interface {
|
||||
Send(*StreamingOutputCallResponse) error
|
||||
Recv() (*StreamingOutputCallRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceFullDuplexCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceFullDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
|
||||
m := new(StreamingOutputCallRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _TestService_HalfDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).HalfDuplexCall(&testServiceHalfDuplexCallServer{stream})
|
||||
}
|
||||
|
||||
type TestService_HalfDuplexCallServer interface {
|
||||
Send(*StreamingOutputCallResponse) error
|
||||
Recv() (*StreamingOutputCallRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServiceHalfDuplexCallServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServiceHalfDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServiceHalfDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
|
||||
m := new(StreamingOutputCallRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// TestService_ServiceDesc is the grpc.ServiceDesc for TestService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var TestService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "testing.TestService",
|
||||
HandlerType: (*TestServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "EmptyCall",
|
||||
Handler: _TestService_EmptyCall_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "UnaryCall",
|
||||
Handler: _TestService_UnaryCall_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "StreamingOutputCall",
|
||||
Handler: _TestService_StreamingOutputCall_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "StreamingInputCall",
|
||||
Handler: _TestService_StreamingInputCall_Handler,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "FullDuplexCall",
|
||||
Handler: _TestService_FullDuplexCall_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "HalfDuplexCall",
|
||||
Handler: _TestService_HalfDuplexCall_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "test.proto",
|
||||
}
|
||||
|
||||
// UnimplementedServiceClient is the client API for UnimplementedService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type UnimplementedServiceClient interface {
|
||||
// A call that no server should implement
|
||||
UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
|
||||
}
|
||||
|
||||
type unimplementedServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewUnimplementedServiceClient(cc grpc.ClientConnInterface) UnimplementedServiceClient {
|
||||
return &unimplementedServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *unimplementedServiceClient) UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
|
||||
out := new(Empty)
|
||||
err := c.cc.Invoke(ctx, "/testing.UnimplementedService/UnimplementedCall", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// UnimplementedServiceServer is the server API for UnimplementedService service.
|
||||
// All implementations must embed UnimplementedUnimplementedServiceServer
|
||||
// for forward compatibility
|
||||
type UnimplementedServiceServer interface {
|
||||
// A call that no server should implement
|
||||
UnimplementedCall(context.Context, *Empty) (*Empty, error)
|
||||
mustEmbedUnimplementedUnimplementedServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedUnimplementedServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedUnimplementedServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedUnimplementedServiceServer) UnimplementedCall(context.Context, *Empty) (*Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnimplementedCall not implemented")
|
||||
}
|
||||
func (UnimplementedUnimplementedServiceServer) mustEmbedUnimplementedUnimplementedServiceServer() {}
|
||||
|
||||
// UnsafeUnimplementedServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to UnimplementedServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeUnimplementedServiceServer interface {
|
||||
mustEmbedUnimplementedUnimplementedServiceServer()
|
||||
}
|
||||
|
||||
func RegisterUnimplementedServiceServer(s grpc.ServiceRegistrar, srv UnimplementedServiceServer) {
|
||||
s.RegisterService(&UnimplementedService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _UnimplementedService_UnimplementedCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UnimplementedServiceServer).UnimplementedCall(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/testing.UnimplementedService/UnimplementedCall",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UnimplementedServiceServer).UnimplementedCall(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// UnimplementedService_ServiceDesc is the grpc.ServiceDesc for UnimplementedService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var UnimplementedService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "testing.UnimplementedService",
|
||||
HandlerType: (*UnimplementedServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "UnimplementedCall",
|
||||
Handler: _UnimplementedService_UnimplementedCall_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "test.proto",
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package testing
|
||||
|
||||
//go:generate protoc --go_out=plugins=grpc:./ test.proto
|
||||
//go:generate protoc --go_out=. --go-grpc_out=. test.proto
|
||||
//go:generate protoc --descriptor_set_out=./test.protoset test.proto
|
||||
//go:generate protoc --descriptor_set_out=./example.protoset --include_imports example.proto
|
||||
|
||||
@@ -19,7 +19,9 @@ import (
|
||||
)
|
||||
|
||||
// TestServer implements the TestService interface defined in example.proto.
|
||||
type TestServer struct{}
|
||||
type TestServer struct {
|
||||
UnimplementedTestServiceServer
|
||||
}
|
||||
|
||||
// EmptyCall accepts one empty request and issues one empty response.
|
||||
func (TestServer) EmptyCall(ctx context.Context, req *Empty) (*Empty, error) {
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"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 we have to import this because it appears in exported API
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
"github.com/jhump/protoreflect/dynamic"
|
||||
"github.com/jhump/protoreflect/dynamic/grpcdynamic"
|
||||
@@ -106,7 +106,7 @@ func InvokeRPC(ctx context.Context, source DescriptorSource, ch grpcdynamic.Chan
|
||||
case isNotFoundError(err):
|
||||
return fmt.Errorf("target server does not expose service %q", svc)
|
||||
}
|
||||
return fmt.Errorf("failed to query for service descriptor %q: %v", svc, err)
|
||||
return fmt.Errorf("failed to query for service descriptor %q: %w", svc, err)
|
||||
}
|
||||
sd, ok := dsc.(*desc.ServiceDescriptor)
|
||||
if !ok {
|
||||
@@ -155,7 +155,7 @@ func invokeUnary(ctx context.Context, stub grpcdynamic.Stub, md *desc.MethodDesc
|
||||
|
||||
err := requestData(req)
|
||||
if err != nil && err != io.EOF {
|
||||
return fmt.Errorf("error getting request data: %v", err)
|
||||
return fmt.Errorf("error getting request data: %w", err)
|
||||
}
|
||||
if err != io.EOF {
|
||||
// verify there is no second message, which is a usage error
|
||||
@@ -163,7 +163,7 @@ func invokeUnary(ctx context.Context, stub grpcdynamic.Stub, md *desc.MethodDesc
|
||||
if err == nil {
|
||||
return fmt.Errorf("method %q is a unary RPC, but request data contained more than 1 message", md.GetFullyQualifiedName())
|
||||
} else if err != io.EOF {
|
||||
return fmt.Errorf("error getting request data: %v", err)
|
||||
return fmt.Errorf("error getting request data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ func invokeClientStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting request data: %v", err)
|
||||
return fmt.Errorf("error getting request data: %w", err)
|
||||
}
|
||||
|
||||
err = str.SendMsg(req)
|
||||
@@ -249,7 +249,7 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
|
||||
|
||||
err := requestData(req)
|
||||
if err != nil && err != io.EOF {
|
||||
return fmt.Errorf("error getting request data: %v", err)
|
||||
return fmt.Errorf("error getting request data: %w", err)
|
||||
}
|
||||
if err != io.EOF {
|
||||
// verify there is no second message, which is a usage error
|
||||
@@ -257,15 +257,17 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
|
||||
if err == nil {
|
||||
return fmt.Errorf("method %q is a server-streaming RPC, but request data contained more than 1 message", md.GetFullyQualifiedName())
|
||||
} else if err != io.EOF {
|
||||
return fmt.Errorf("error getting request data: %v", err)
|
||||
return fmt.Errorf("error getting request data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Now we can actually invoke the RPC!
|
||||
str, err := stub.InvokeRpcServerStream(ctx, md, req)
|
||||
|
||||
if respHeaders, err := str.Header(); err == nil {
|
||||
handler.OnReceiveHeaders(respHeaders)
|
||||
if str != nil {
|
||||
if respHeaders, err := str.Header(); err == nil {
|
||||
handler.OnReceiveHeaders(respHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
// Download each response message
|
||||
@@ -288,7 +290,9 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
|
||||
return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err)
|
||||
}
|
||||
|
||||
handler.OnReceiveTrailers(stat, str.Trailer())
|
||||
if str != nil {
|
||||
handler.OnReceiveTrailers(stat, str.Trailer())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -322,7 +326,7 @@ func invokeBidi(ctx context.Context, stub grpcdynamic.Stub, md *desc.MethodDescr
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error getting request data: %v", err)
|
||||
err = fmt.Errorf("error getting request data: %w", err)
|
||||
cancel()
|
||||
break
|
||||
}
|
||||
|
||||
+14
-71
@@ -7,84 +7,27 @@ The release process consists of a handful of tasks:
|
||||
2. Build binaries for various platforms. This is done using the local `go` tool and uses `GOOS` and `GOARCH` environment variables to cross-compile for supported platforms.
|
||||
3. Creates a release in GitHub, uploads the binaries, and creates provisional release notes (in the form of a change log).
|
||||
4. Build a docker image for the new release.
|
||||
5. Push the docker image to Docker Hub, with both a version tag and the "latest" tag.
|
||||
6. Submits a PR to update the [Homebrew](https://brew.sh/) recipe with the latest version.
|
||||
5. Push the docker image to `ghcr.io`, with both a version tag and the "latest" tag.
|
||||
|
||||
Most of this is automated via a script in this same directory. The main thing you will need is a GitHub personal access token, which will be used for creating the release in GitHub (so you need write access to the fullstorydev/grpcurl repo) and to open a Homebrew pull request.
|
||||
|
||||
## Creating a new release
|
||||
|
||||
So, to actually create a new release, just run the script in this directory.
|
||||
Go to the [Release workflow](https://github.com/fullstorydev/grpcurl/actions/workflows/release.yml), click **Run workflow**, and provide:
|
||||
|
||||
First, you need a version number for the new release, following sem-ver format: `v<Major>.<Minor>.<Patch>`. Second, you need a personal access token for GitHub.
|
||||
* **Branch**: the branch or commit to release from (usually `master`).
|
||||
* **version**: the version number for the new release, in sem-ver format: `v<Major>.<Minor>.<Patch>`, e.g. `v2.3.4`.
|
||||
* **dry_run**: check this to build everything but publish nothing. Useful for validating a change to the release tooling. The binaries are attached to the workflow run as an artifact.
|
||||
|
||||
We'll use `v2.3.4` as an example version and `abcdef0123456789abcdef` as an example GitHub token:
|
||||
The workflow then:
|
||||
1. Verifies the version is well-formed and that the tag does not already exist.
|
||||
2. Runs the tests.
|
||||
3. Creates and pushes the release tag.
|
||||
4. Cross-compiles binaries for all supported platforms, creates the GitHub release with generated release notes, and uploads the archives. (This is goreleaser, driven by `.goreleaser.yml`.)
|
||||
5. Builds a multi-arch (`linux/amd64`, `linux/arm64`) Docker image and pushes it to `ghcr.io`, tagged with both the version and `latest`.
|
||||
|
||||
```sh
|
||||
# from the root of the repo
|
||||
GITHUB_TOKEN=abcdef0123456789abcd \
|
||||
./releasing/do-release.sh v2.3.4
|
||||
```
|
||||
## Release notes
|
||||
|
||||
Wasn't that easy! There is one last step: update the release notes in GitHub. By default, the script just records a change log of commit descriptions. Use that log (and, if necessary, drill into individual PRs included in the release) to flesh out notes in the format of the `RELEASE_NOTES.md` file _in this directory_. Then login to GitHub, go to the new release, edit the notes, and paste in the markdown you just wrote.
|
||||
Release notes are generated, never hand-written. `changelog.use: github-native` in `.goreleaser.yml` hands the job to GitHub's own release-notes generator, which lists every PR merged since the previous tag with its title, link, and author, and credits new contributors.
|
||||
|
||||
That should be all there is to it! If things go wrong and you have to re-do part of the process, see the sections below.
|
||||
|
||||
----
|
||||
|
||||
### GitHub Releases
|
||||
The GitHub release is the first step performed by the `do-release.sh` script. So generally, if there is an issue with that step, you can re-try the whole script.
|
||||
|
||||
Note, if running the script did something wrong, you may have to first login to GitHub and remove uploaded artifacts for a botched release attempt. In general, this is _very undesirable_. Releases should usually be considered immutable. Instead of removing uploaded assets and providing new ones, it is often better to remove uploaded assets (to make bad binaries no longer available) and then _release a new patch version_. (You can edit the release notes for the botched version explaining why there are no artifacts for it.)
|
||||
|
||||
The steps to do a GitHub-only release (vs. running the entire script) are the following:
|
||||
|
||||
```sh
|
||||
# from the root of the repo
|
||||
git tag v2.3.4
|
||||
GITHUB_TOKEN=abcdef0123456789abcdef \
|
||||
GO111MODULE=on \
|
||||
make release
|
||||
```
|
||||
|
||||
The `git tag ...` step is necessary because the release target requires that the current SHA have a sem-ver tag. That's the version it will use when creating the release.
|
||||
|
||||
This will create the release in GitHub with provisional release notes that just include a change log of commit messages. You still need to login to GitHub and revise those notes to adhere to the recommended format. (See `RELEASE_NOTES.md` in this directory.)
|
||||
|
||||
### Docker Hub Releases
|
||||
|
||||
To re-run only the Docker Hub release steps, we need to build an image with the right tag and then push to Docker Hub.
|
||||
|
||||
```sh
|
||||
# from the root of the repo
|
||||
echo v2.3.4 > VERSION
|
||||
docker build -t fullstorydev/grpcurl:v2.3.4 .
|
||||
# now that we have it built, push to Docker Hub
|
||||
docker push fullstorydev/grpcurl:v2.3.4
|
||||
# push "latest" tag, too
|
||||
docker tag fullstorydev/grpcurl:v2.3.4 fullstorydev/grpcurl:latest
|
||||
docker push fullstorydev/grpcurl:latest
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
### Homebrew Releases
|
||||
|
||||
The last step is to update the Homebrew recipe to use the latest version. First, we need to compute the SHA256 checksum for the source archive:
|
||||
|
||||
```sh
|
||||
# download the source archive from GitHub
|
||||
URL=https://github.com/fullstorydev/grpcurl/archive/v2.3.4.tar.gz
|
||||
curl -L -o tmp.tgz $URL
|
||||
# and compute the SHA
|
||||
SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')"
|
||||
```
|
||||
|
||||
To actually create the brew PR, you need your GitHub personal access token again, as well as the URL and SHA from the previous step:
|
||||
|
||||
```sh
|
||||
HOMEBREW_GITHUB_API_TOKEN=abcdef0123456789abcdef \
|
||||
brew bump-formula-pr --url $URL --sha256 $SHA grpcurl
|
||||
```
|
||||
|
||||
This creates a PR to bump the formula to the new version. When this PR is merged by brew maintainers, the new version becomes available!
|
||||
`.github/release.yml` controls how those PRs are grouped. Labels are optional — an unlabeled PR lands in a catch-all "Changes" section — so this needs no ongoing upkeep. Two things make the notes read better, if you want them:
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
## Changes
|
||||
|
||||
### Command-line tool
|
||||
|
||||
* _In this list, describe the changes to the command-line tool._
|
||||
* _Use one bullet per change. Include both bug-fixes and improvements. Omit this section if there are no changes that impact the command-line tool._
|
||||
|
||||
### Go package "github.com/fullstorydev/grpcurl"
|
||||
|
||||
* _In this list, describe the changes to exported API in the main package in this repo: "github.com/fullstorydev/grpcurl". These will often be closely related to changes to the command-line tool, though not always: changes that only impact the cmd/grpcurl directory of this repo do not impact exported API._
|
||||
* _Use one bullet per change. Include both bug-fixes and improvements. Omit this section if there are no changes that impact the exported API._
|
||||
+10
-11
@@ -37,8 +37,9 @@ $PREFIX git checkout go.mod go.sum
|
||||
|
||||
# make sure credentials are valid for later push steps; this might
|
||||
# be interactive since this will prompt for username and password
|
||||
# if there are no valid current credentials.
|
||||
$PREFIX docker login
|
||||
# if there are no valid current credentials. Use a GitHub personal access
|
||||
# token with the write:packages scope as the password.
|
||||
$PREFIX docker login ghcr.io
|
||||
echo "$VERSION" > VERSION
|
||||
|
||||
# Docker Buildx support is included in Docker 19.03
|
||||
@@ -47,15 +48,13 @@ echo "$VERSION" > VERSION
|
||||
$PREFIX docker run --privileged --rm tonistiigi/binfmt:qemu-v6.1.0 --install all
|
||||
# Create a new builder instance
|
||||
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
$PREFIX docker buildx create --use --name multiarch-builder
|
||||
# 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 --tag fullstorydev/grpcurl:${VERSION} --tag fullstorydev/grpcurl:latest --push --progress plain --no-cache .
|
||||
$PREFIX docker buildx create --use --name multiarch-builder --node multiarch-builder0
|
||||
# push to GHCR, 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 ghcr.io/fullstorydev/grpcurl:${VERSION} --tag ghcr.io/fullstorydev/grpcurl:latest --push --progress plain --no-cache .
|
||||
$PREFIX docker buildx build --platform linux/amd64,linux/s390x,linux/arm64,linux/ppc64le --tag ghcr.io/fullstorydev/grpcurl:${VERSION}-alpine --tag ghcr.io/fullstorydev/grpcurl:latest-alpine --push --progress plain --no-cache --target alpine .
|
||||
rm VERSION
|
||||
|
||||
# Homebrew release
|
||||
|
||||
URL="https://github.com/fullstorydev/grpcurl/archive/${VERSION}.tar.gz"
|
||||
curl -L -o tmp.tgz "$URL"
|
||||
SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')"
|
||||
rm tmp.tgz
|
||||
HOMEBREW_GITHUB_API_TOKEN="$GITHUB_TOKEN" $PREFIX brew bump-formula-pr --url "$URL" --sha256 "$SHA" grpcurl
|
||||
#
|
||||
# Nothing to do. Homebrew's tooling polls for new releases and opens the
|
||||
# homebrew-core bump PR on its own. See releasing/README.md.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# packing and releasing
|
||||
To pack the current branch to a snap package:
|
||||
|
||||
`snapcraft pack`
|
||||
|
||||
To install the package locally:
|
||||
|
||||
`snap install ./grpcurl_v[version tag]_amd64.snap --devmode`
|
||||
|
||||
To upload the snap to the edge channel:
|
||||
|
||||
`snapcraft upload --release edge ./grpcurl_v[version tag]_amd64.snap`
|
||||
|
||||
(you need to own the package name registration for this!)
|
||||
|
||||
# ownership
|
||||
The snap's current owner is `pietro.pasotti@canonical.com`; who is very happy to support with maintaining the snap distribution and/or transfer its ownership to the developers.
|
||||
|
||||
Please reach out to me for questions regarding the snap; including:
|
||||
- adding support for other architectures
|
||||
- automating the release
|
||||
|
||||
Cheers and thanks for the awesome tool!
|
||||
@@ -0,0 +1,47 @@
|
||||
name: grpcurl
|
||||
base: core24
|
||||
# allow grpcurl part to call craftctl set-version
|
||||
adopt-info: grpcurl
|
||||
summary: grpcurl is a command-line tool that lets you interact with gRPC servers.
|
||||
|
||||
description: |
|
||||
grpcurl is a command-line tool that lets you interact with gRPC servers.
|
||||
It's basically curl for gRPC servers.
|
||||
|
||||
grade: stable
|
||||
confinement: strict
|
||||
license: MIT
|
||||
|
||||
platforms:
|
||||
amd64:
|
||||
build-on:
|
||||
- amd64
|
||||
build-for:
|
||||
- amd64
|
||||
arm64:
|
||||
build-on:
|
||||
- amd64
|
||||
- arm64
|
||||
build-for:
|
||||
- arm64
|
||||
|
||||
apps:
|
||||
grpcurl:
|
||||
command: grpcurl
|
||||
plugs:
|
||||
- network
|
||||
|
||||
parts:
|
||||
grpcurl:
|
||||
plugin: go
|
||||
build-snaps: [go/latest/stable]
|
||||
source: https://github.com/fullstorydev/grpcurl
|
||||
source-type: git
|
||||
override-build: |
|
||||
tag="$(git describe --tags --abbrev=0)"
|
||||
craftctl set version="$tag"
|
||||
|
||||
go build -o $CRAFT_PART_INSTALL/grpcurl ./cmd/grpcurl/grpcurl.go
|
||||
|
||||
# adjust the permissions
|
||||
chmod 0755 $CRAFT_PART_INSTALL/grpcurl
|
||||
+98
-63
@@ -2,6 +2,7 @@ package grpcurl_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/peer"
|
||||
|
||||
. "github.com/fullstorydev/grpcurl"
|
||||
grpcurl_testing "github.com/fullstorydev/grpcurl/internal/testing"
|
||||
@@ -101,64 +103,85 @@ func TestRequireClientCertTLS(t *testing.T) {
|
||||
simpleTest(t, e.cc)
|
||||
}
|
||||
|
||||
func TestTLS12(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
tlsConf, err := ClientTLSConfig(false, "internal/testing/tls/ca.crt", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create client TLS config: %v", err)
|
||||
}
|
||||
tlsConf.MaxVersion = tls.VersionTLS12
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, credentials.NewTLS(tlsConf))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to setup server and client: %v", err)
|
||||
}
|
||||
defer e.Close()
|
||||
|
||||
tlsVersion := negotiatedTLSVersion(t, e.cc)
|
||||
if tlsVersion != tls.VersionTLS12 {
|
||||
t.Errorf("expected TLS 1.2, got 0x%04x", tlsVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLS13(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create client creds: %v", err)
|
||||
}
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to setup server and client: %v", err)
|
||||
}
|
||||
defer e.Close()
|
||||
|
||||
tlsVersion := negotiatedTLSVersion(t, e.cc)
|
||||
if tlsVersion != tls.VersionTLS13 {
|
||||
t.Errorf("expected TLS 1.3, got 0x%04x", tlsVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func negotiatedTLSVersion(t *testing.T, cc *grpc.ClientConn) uint16 {
|
||||
t.Helper()
|
||||
cl := grpcurl_testing.NewTestServiceClient(cc)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
var p peer.Peer
|
||||
_, err := cl.UnaryCall(ctx, &grpcurl_testing.SimpleRequest{}, grpc.WaitForReady(true), grpc.Peer(&p))
|
||||
if err != nil {
|
||||
t.Fatalf("RPC failed: %v", err)
|
||||
}
|
||||
tlsInfo, ok := p.AuthInfo.(credentials.TLSInfo)
|
||||
if !ok {
|
||||
t.Fatalf("expected TLS auth info, got %T", p.AuthInfo)
|
||||
}
|
||||
return tlsInfo.State.Version
|
||||
}
|
||||
|
||||
func TestBrokenTLS_ClientPlainText(t *testing.T) {
|
||||
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server creds: %v", err)
|
||||
}
|
||||
|
||||
// client connection (usually) succeeds since client is not waiting for TLS handshake
|
||||
// (we try several times, but if we never get a connection and the error message is
|
||||
// a known/expected possibility, we'll just bail)
|
||||
var e testEnv
|
||||
failCount := 0
|
||||
for {
|
||||
e, err = createTestServerAndClient(serverCreds, nil)
|
||||
if err == nil {
|
||||
// success!
|
||||
defer e.Close()
|
||||
break
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "deadline exceeded") ||
|
||||
strings.Contains(err.Error(), "use of closed network connection") {
|
||||
// It is possible that the connection never becomes healthy:
|
||||
// 1) grpc connects successfully
|
||||
// 2) grpc client tries to send HTTP/2 preface and settings frame
|
||||
// 3) server, expecting handshake, closes the connection
|
||||
// 4) in the client, the write fails, so the connection never
|
||||
// becomes ready
|
||||
// The client will attempt to reconnect on transient errors, so
|
||||
// may eventually bump into the connect time limit. This used to
|
||||
// result in a "deadline exceeded" error, but more recent versions
|
||||
// of the grpc library report any underlying I/O error instead, so
|
||||
// we also check for "use of closed network connection".
|
||||
failCount++
|
||||
if failCount > 5 {
|
||||
return // bail...
|
||||
}
|
||||
// we'll try again
|
||||
|
||||
} else {
|
||||
// some other error occurred, so we'll consider that a test failure
|
||||
t.Fatalf("failed to setup server and client: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// but request fails because server closes connection upon seeing request
|
||||
// bytes that are not a TLS handshake
|
||||
cl := grpcurl_testing.NewTestServiceClient(e.cc)
|
||||
_, err = cl.UnaryCall(context.Background(), &grpcurl_testing.SimpleRequest{})
|
||||
// Plaintext client to TLS server: the server expects a TLS handshake,
|
||||
// gets an HTTP/2 preface instead, and closes the connection.
|
||||
e, err := createTestServerAndClient(serverCreds, nil)
|
||||
if err == nil {
|
||||
t.Fatal("expecting failure")
|
||||
e.Close()
|
||||
t.Fatal("expecting failure when connecting plaintext to TLS server")
|
||||
}
|
||||
// various errors possible when server closes connection
|
||||
if !strings.Contains(err.Error(), "transport is closing") &&
|
||||
!strings.Contains(err.Error(), "connection is unavailable") &&
|
||||
if !strings.Contains(err.Error(), "EOF") &&
|
||||
!strings.Contains(err.Error(), "use of closed network connection") &&
|
||||
!strings.Contains(err.Error(), "all SubConns are in TransientFailure") {
|
||||
|
||||
t.Fatalf("expecting transport failure, got: %v", err)
|
||||
!strings.Contains(err.Error(), "connection reset by peer") {
|
||||
t.Fatalf("expecting connection closed error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,8 +193,8 @@ func TestBrokenTLS_ServerPlainText(t *testing.T) {
|
||||
|
||||
e, err := createTestServerAndClient(nil, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "first record does not look like a TLS handshake") {
|
||||
t.Fatalf("expecting TLS handshake failure, got: %v", err)
|
||||
@@ -190,8 +213,8 @@ func TestBrokenTLS_ServerUsesWrongCert(t *testing.T) {
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "certificate is valid for") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
@@ -210,10 +233,10 @@ func TestBrokenTLS_ClientHasExpiredCert(t *testing.T) {
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "bad certificate") {
|
||||
if !strings.Contains(err.Error(), "certificate") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -230,8 +253,8 @@ func TestBrokenTLS_ServerHasExpiredCert(t *testing.T) {
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "certificate has expired or is not yet valid") {
|
||||
t.Fatalf("expecting TLS certificate expired, got: %v", err)
|
||||
@@ -250,11 +273,17 @@ func TestBrokenTLS_ClientNotTrusted(t *testing.T) {
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "bad certificate") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
// The exact TLS alert varies by Go version and TLS version negotiated:
|
||||
// - TLS 1.2: "bad certificate" (Go <=1.24) or "handshake failure" (Go 1.25+)
|
||||
// - TLS 1.3: "certificate required" (server rejects after handshake)
|
||||
errMsg := err.Error()
|
||||
if !strings.Contains(errMsg, "bad certificate") &&
|
||||
!strings.Contains(errMsg, "handshake failure") &&
|
||||
!strings.Contains(errMsg, "certificate required") {
|
||||
t.Fatalf("expecting a TLS certificate error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,10 +299,10 @@ func TestBrokenTLS_ServerNotTrusted(t *testing.T) {
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "certificate signed by unknown authority") {
|
||||
if !strings.Contains(err.Error(), "certificate") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -290,11 +319,17 @@ func TestBrokenTLS_RequireClientCertButNonePresented(t *testing.T) {
|
||||
|
||||
e, err := createTestServerAndClient(serverCreds, clientCreds)
|
||||
if err == nil {
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
e.Close()
|
||||
t.Fatal("expecting TLS failure setting up server and client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "bad certificate") {
|
||||
t.Fatalf("expecting TLS certificate error, got: %v", err)
|
||||
// The exact TLS alert varies by Go version and TLS version negotiated:
|
||||
// - TLS 1.2: "bad certificate" (Go <=1.24) or "handshake failure" (Go 1.25+)
|
||||
// - TLS 1.3: "certificate required" (server rejects after handshake)
|
||||
errMsg := err.Error()
|
||||
if !strings.Contains(errMsg, "bad certificate") &&
|
||||
!strings.Contains(errMsg, "handshake failure") &&
|
||||
!strings.Contains(errMsg, "certificate required") {
|
||||
t.Fatalf("expecting a TLS certificate error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,7 +384,7 @@ type testEnv struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func (e testEnv) Close() {
|
||||
func (e *testEnv) Close() {
|
||||
if e.cc != nil {
|
||||
e.cc.Close()
|
||||
e.cc = nil
|
||||
|
||||
Reference in New Issue
Block a user