update kubernetes dependencies to v1.25.0

Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
This commit is contained in:
Humble Chirammal
2022-08-24 09:59:15 +05:30
parent 233034c400
commit 71923eb321
374 changed files with 17777 additions and 5208 deletions

92
go.mod
View File

@@ -3,7 +3,7 @@ module github.com/kubernetes-csi/external-snapshotter/v6
go 1.17 go 1.17
require ( require (
github.com/container-storage-interface/spec v1.5.0 github.com/container-storage-interface/spec v1.6.0
github.com/evanphx/json-patch v4.12.0+incompatible github.com/evanphx/json-patch v4.12.0+incompatible
github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify v1.4.9
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
@@ -16,14 +16,14 @@ require (
github.com/prometheus/client_model v0.2.0 github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.32.1 github.com/prometheus/common v0.32.1
github.com/spf13/cobra v1.4.0 github.com/spf13/cobra v1.4.0
google.golang.org/grpc v1.40.0 google.golang.org/grpc v1.47.0
k8s.io/api v0.24.3 k8s.io/api v0.25.0
k8s.io/apimachinery v0.24.3 k8s.io/apimachinery v0.25.0
k8s.io/client-go v0.24.3 k8s.io/client-go v0.25.0
k8s.io/component-base v0.24.3 k8s.io/component-base v0.25.0
k8s.io/component-helpers v0.24.3 k8s.io/component-helpers v0.25.0
k8s.io/klog/v2 v2.60.1 k8s.io/klog/v2 v2.70.1
k8s.io/kubernetes v1.24.3 k8s.io/kubernetes v1.25.0
) )
require ( require (
@@ -34,7 +34,7 @@ require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/go-logr/logr v1.2.0 // indirect github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect github.com/go-openapi/swag v0.19.14 // indirect
@@ -54,53 +54,53 @@ require (
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/procfs v0.7.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect
google.golang.org/protobuf v1.27.1 // indirect google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog v1.0.0 // indirect k8s.io/klog v1.0.0 // indirect
k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 // indirect k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect sigs.k8s.io/yaml v1.3.0 // indirect
) )
replace ( replace (
github.com/kubernetes-csi/external-snapshotter/client/v6 => ./client github.com/kubernetes-csi/external-snapshotter/client/v6 => ./client
k8s.io/api => k8s.io/api v0.24.3 k8s.io/api => k8s.io/api v0.25.0
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.24.3 k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.25.0
k8s.io/apimachinery => k8s.io/apimachinery v0.24.3 k8s.io/apimachinery => k8s.io/apimachinery v0.26.0-alpha.0
k8s.io/apiserver => k8s.io/apiserver v0.24.3 k8s.io/apiserver => k8s.io/apiserver v0.25.0
k8s.io/cli-runtime => k8s.io/cli-runtime v0.24.3 k8s.io/cli-runtime => k8s.io/cli-runtime v0.25.0
k8s.io/client-go => k8s.io/client-go v0.24.3 k8s.io/client-go => k8s.io/client-go v0.25.0
k8s.io/cloud-provider => k8s.io/cloud-provider v0.24.3 k8s.io/cloud-provider => k8s.io/cloud-provider v0.25.0
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.24.3 k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.25.0
k8s.io/code-generator => k8s.io/code-generator v0.24.3 k8s.io/code-generator => k8s.io/code-generator v0.25.0
k8s.io/component-base => k8s.io/component-base v0.24.3 k8s.io/component-base => k8s.io/component-base v0.25.0
k8s.io/component-helpers => k8s.io/component-helpers v0.24.3 k8s.io/component-helpers => k8s.io/component-helpers v0.25.0
k8s.io/controller-manager => k8s.io/controller-manager v0.24.3 k8s.io/controller-manager => k8s.io/controller-manager v0.25.0
k8s.io/cri-api => k8s.io/cri-api v0.24.3 k8s.io/cri-api => k8s.io/cri-api v0.25.0
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.24.3 k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.25.0
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.24.3 k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.25.0
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.24.3 k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.25.0
k8s.io/kube-proxy => k8s.io/kube-proxy v0.24.3 k8s.io/kube-proxy => k8s.io/kube-proxy v0.25.0
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.24.3 k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.25.0
k8s.io/kubectl => k8s.io/kubectl v0.24.3 k8s.io/kubectl => k8s.io/kubectl v0.25.0
k8s.io/kubelet => k8s.io/kubelet v0.24.3 k8s.io/kubelet => k8s.io/kubelet v0.25.0
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.24.3 k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.25.0
k8s.io/metrics => k8s.io/metrics v0.24.3 k8s.io/metrics => k8s.io/metrics v0.25.0
k8s.io/mount-utils => k8s.io/mount-utils v0.24.3 k8s.io/mount-utils => k8s.io/mount-utils v0.25.0
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.24.3 k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.25.0
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.24.3 k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.25.0
k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.24.3 k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.25.0
k8s.io/sample-controller => k8s.io/sample-controller v0.24.3 k8s.io/sample-controller => k8s.io/sample-controller v0.25.0
) )

286
go.sum
View File

@@ -1,5 +1,5 @@
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
bitbucket.org/bertimus9/systemstat v0.0.0-20180207000608-0eeff89b0690/go.mod h1:Ulb78X89vxKYgdL24HMTiXYHlyHEvruOj1ZPlqeNEZM= bitbucket.org/bertimus9/systemstat v0.5.0/go.mod h1:EkUWPp8lKFPMXP8vnbpT5JDI0W/sTiLZAvN8ONWErHY=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 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.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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -20,6 +20,13 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 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.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@@ -43,19 +50,21 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7
github.com/Azure/azure-sdk-for-go v55.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v55.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 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/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/GoogleCloudPlatform/k8s-cloud-provider v1.16.1-0.20210702024009-ea6160c1d0e3/go.mod h1:8XasY4ymP2V/tn2OOV9ZadmiTE1FIB/h3W+yNlPttKw= github.com/GoogleCloudPlatform/k8s-cloud-provider v1.18.1-0.20220218231025-f11817397a1b/go.mod h1:FNj4KYEAAHfYu68kRYolGoxkaJn+6mdEsaM12VTwuI0=
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0= github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0=
@@ -73,7 +82,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -91,7 +100,6 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
@@ -105,7 +113,7 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 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/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@@ -113,30 +121,33 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
github.com/container-storage-interface/spec v1.3.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= github.com/container-storage-interface/spec v1.3.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4=
github.com/container-storage-interface/spec v1.5.0 h1:lvKxe3uLgqQeVQcrnL2CPQKISoKjTJxojEs9cBk+HXo=
github.com/container-storage-interface/spec v1.5.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s= github.com/container-storage-interface/spec v1.5.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s=
github.com/container-storage-interface/spec v1.6.0 h1:vwN9uCciKygX/a0toYryoYD5+qI9ZFeAMuhEEKO+JBA=
github.com/container-storage-interface/spec v1.6.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s=
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.4.12/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
github.com/coredns/corefile-migration v1.0.14/go.mod h1:XnhgULOEouimnzgn0t4WPuFDN2/PJQcTxdWKC5eXNGE= github.com/coredns/corefile-migration v1.0.17/go.mod h1:XnhgULOEouimnzgn0t4WPuFDN2/PJQcTxdWKC5eXNGE=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -156,13 +167,12 @@ github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxG
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= github.com/daviddengcn/go-colortext v1.0.0/go.mod h1:zDqEI5NVUop5QPpVJUxE9UO10hRnmkD5G4Pmri9+m4c=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
@@ -171,6 +181,7 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkg
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful/v3 v3.5.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -180,6 +191,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -214,9 +226,11 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@@ -233,11 +247,14 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
@@ -275,13 +292,16 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
github.com/golangplus/bytes v1.0.0/go.mod h1:AdRaCFwmc/00ZzELMWb01soso6W1R/++O1XL80yAn+A=
github.com/golangplus/fmt v1.0.0/go.mod h1:zpM0OfbMCjPtd2qkTD/jX2MgiFCqklhSUFyDW44gVQE=
github.com/golangplus/testing v1.0.0/go.mod h1:ZDreixUV3YzhoVraIDyOzHrr76p6NUh6k/pPg/Q3gYA=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 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/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/cadvisor v0.44.1/go.mod h1:GQ9KQfz0iNHQk3D6ftzJWK4TXabfIgM10Oy3FkR+Gzg= github.com/google/cadvisor v0.45.0/go.mod h1:vsMT3Uv2XjQ8M7WUtKARV74mU/HN64C4XtM1bJhUKcU=
github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= github.com/google/cel-go v0.12.4/go.mod h1:Av7CU6r6X3YmcHR9GXqVDaEJYfEtSxl6wvIjUQTriCw=
github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -304,6 +324,7 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 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-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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -316,6 +337,9 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -323,7 +347,8 @@ 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/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.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -362,7 +387,7 @@ github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7U
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
@@ -413,10 +438,8 @@ github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z
github.com/lpabon/godbc v0.1.1/go.mod h1:Jo9QV0cf3U6jZABgiJ2skINAXb9j8m51r07g4KI92ZA= github.com/lpabon/godbc v0.1.1/go.mod h1:Jo9QV0cf3U6jZABgiJ2skINAXb9j8m51r07g4KI92ZA=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -471,7 +494,6 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
@@ -486,8 +508,7 @@ github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/opencontainers/runc v1.1.1/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -495,7 +516,6 @@ github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuh
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -505,12 +525,13 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -534,7 +555,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quobyte/api v0.1.8/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
@@ -547,7 +567,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -566,23 +586,17 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/storageos/go-api v2.2.0+incompatible/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
@@ -606,7 +620,7 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 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.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -614,18 +628,16 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/pkg/v3 v3.5.4/go.mod h1:OI+TtO+Aa3nhQSppMbwE4ld3uF1/fqqwbpfndbbrEe0=
go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= go.etcd.io/etcd/raft/v3 v3.5.4/go.mod h1:SCuunjYvZFC0fBX0vxMSPjuZmpcSk+XaAcMrD6Do03w=
go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= go.etcd.io/etcd/server/v3 v3.5.4/go.mod h1:S5/YTU15KxymM5l3T6b09sNOHPXqGYIZStpuuGbb65c=
go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE=
go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc=
go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 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.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -634,8 +646,10 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.20.0/go.mod h1:oQkZOyq61qZBItEFqhfpobK6X/oDPR7/Qr+MXjVSTks=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
go.opentelemetry.io/contrib/propagators v0.20.0/go.mod h1:yLmt93MeSiARUwrK57bOZ4FBruRN4taLiW1lcGfnOes=
go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
@@ -663,9 +677,10 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/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/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -712,6 +727,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -762,12 +778,12 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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-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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -779,9 +795,11 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -795,6 +813,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -839,7 +858,6 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -862,13 +880,17 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -876,8 +898,9 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -958,9 +981,12 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -993,8 +1019,15 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.60.0/go.mod h1:d7rl65NZAkEQ90JFzqBjcRq1TVeG5ZoGV3sSpEnnVb4=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 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.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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1038,7 +1071,6 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -1048,11 +1080,25 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 h1:Et6SkiuvnBn+SgrSYXs/BrUpGB4mbdwt4R3vaPIlicA= google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I=
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 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.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -1074,9 +1120,15 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 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-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 v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1089,8 +1141,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 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-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1103,7 +1156,6 @@ gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
@@ -1122,8 +1174,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -1133,26 +1186,25 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 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.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.24.3 h1:tt55QEmKd6L2k5DP6G/ZzdMQKvG5ro4H4teClqm0sTY= k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0=
k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI= k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk=
k8s.io/apiextensions-apiserver v0.24.3/go.mod h1:cL0xkmUefpYM4f6IuOau+6NMFEIh6/7wXe/O4vPVJ8A= k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E=
k8s.io/apimachinery v0.24.3 h1:hrFiNSA2cBZqllakVYyH/VyEh4B581bQRmqATJSeQTg= k8s.io/apimachinery v0.26.0-alpha.0 h1:cnXW2EigxCOrD+s52R9r5AZOcu1Nbv508gOCgSQkbo4=
k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= k8s.io/apimachinery v0.26.0-alpha.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0=
k8s.io/apiserver v0.24.3/go.mod h1:aXfwtIn4U27B7lYs5f2BKgz6DRbgWy+HJeYReN1jLJ8= k8s.io/apiserver v0.25.0/go.mod h1:BKwsE+PTC+aZK+6OJQDPr0v6uS91/HWxX7evElAH6xo=
k8s.io/cli-runtime v0.24.3/go.mod h1:In84wauoMOqa7JDvDSXGbf8lTNlr70fOGpYlYfJtSqA= k8s.io/cli-runtime v0.25.0/go.mod h1:bHOI5ZZInRHhbq12OdUiYZQN8ml8aKZLwQgt9QlLINw=
k8s.io/client-go v0.24.3 h1:Nl1840+6p4JqkFWEW2LnMKU667BUxw03REfLAVhuKQY= k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E=
k8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw= k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8=
k8s.io/cloud-provider v0.24.3/go.mod h1:CRIMwnR4e6FpGO5g81nofNuKGQcpJx8El2JEU+BsH9M= k8s.io/cloud-provider v0.25.0/go.mod h1:afVfVCIYOUER914WmSp0QpAtJn12gv4qu9NMT4XBxZo=
k8s.io/cluster-bootstrap v0.24.3/go.mod h1:plud10KCFfNjsf2FNalENFGvJWVtcKa0KbKie5wQAvA= k8s.io/cluster-bootstrap v0.25.0/go.mod h1:x/TCtY3EiuR/rODkA3SvVQT3uSssQLf9cXcmSjdDTe0=
k8s.io/code-generator v0.24.3/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/code-generator v0.25.0/go.mod h1:B6jZgI3DvDFAualltPitbYMQ74NjaCFxum3YeKZZ+3w=
k8s.io/component-base v0.24.3 h1:u99WjuHYCRJjS1xeLOx72DdRaghuDnuMgueiGMFy1ec= k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y=
k8s.io/component-base v0.24.3/go.mod h1:bqom2IWN9Lj+vwAkPNOv2TflsP1PeVDIwIN0lRthxYY= k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk=
k8s.io/component-helpers v0.24.3 h1:HKZTNf77K96StY2+FAgKvsXvHwoLvexeGDJatyuWlyI= k8s.io/component-helpers v0.25.0 h1:vNzYfqnVXj7f+CPksduKVv2Z9kC+IDsOs9yaOyxZrj0=
k8s.io/component-helpers v0.24.3/go.mod h1:/1WNW8TfBOijQ1ED2uCHb4wtXYWDVNMqUll8h36iNVo= k8s.io/component-helpers v0.25.0/go.mod h1:auaFj2bvb5Zmy0mLk4WJNmwP0w4e7Zk+/Tu9FFBGA20=
k8s.io/controller-manager v0.24.3/go.mod h1:qU/ZC8qmKxiVlRwLUfqXAzgsBi3q44E8Xn8qHs/MiVY= k8s.io/controller-manager v0.25.0/go.mod h1:QElCivPrZ64NP1Y976pkgyViZUqn6UcvjlXHiAAUGd0=
k8s.io/cri-api v0.24.3/go.mod h1:t3tImFtGeStN+ES69bQUX9sFg67ek38BM9YIJhMmuig= k8s.io/cri-api v0.25.0/go.mod h1:J1rAyQkSJ2Q6I+aBMOVgg2/cbbebso6FNa0UagiR0kc=
k8s.io/csi-translation-lib v0.24.3/go.mod h1:PfajTaauPYSL4hWKDRBVbUfO611Uv+h3w1YA9Twmzjk= k8s.io/csi-translation-lib v0.25.0/go.mod h1:Wb80CDywP4753F6wWkIyOuJIQtQAbhgw985veSgAn/4=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
@@ -1161,30 +1213,32 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc=
k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-aggregator v0.24.3/go.mod h1:oMjdwraZtb0CtIxrzrAt/4GJxbivAM8AesZhYVmXZ54= k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
k8s.io/kube-controller-manager v0.24.3/go.mod h1:c7YN1XesvesxKM5uO5JqmcecnUsitFos1sIyt0eOprE= k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-aggregator v0.25.0/go.mod h1:dfdl4aQkleiWK/U++UDLdDC8g2rsonhkB23zzUeBCgM=
k8s.io/kube-controller-manager v0.25.0/go.mod h1:SjL1hKSG2z9wajnvjRHZv1zOsdDHjmbZd1ykmaYO6J8=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 h1:yEQKdMCjzAOvGeiTwG4hO/hNVNtDOuUFvMUZ0OlaIzs= k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661/go.mod h1:daOouuuwd9JXpv1L7Y34iV3yf6nxzipkKMWWlqlvK9M=
k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8/go.mod h1:mbJ+NSUoAhuR14N0S63bPkh8MGVSo3VYSGZtH/mfMe0= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
k8s.io/kube-proxy v0.24.3/go.mod h1:zJ+koqfBkRUAzUfXlBtFfyfH3InqM38t5ELGlTlPwO0= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
k8s.io/kube-scheduler v0.24.3/go.mod h1:myFLGrPy8rcwPz6qg9L3rMRDT2eNIpizq+MXOzMjX/8= k8s.io/kube-proxy v0.25.0/go.mod h1:uHv1HwMVDYgl1pU2PTDKLRlxtNOf4z2M5YPYC6NP1CU=
k8s.io/kubectl v0.24.3/go.mod h1:PYLcvw96sC1NLbxZEDbdlOEd6/C76VIWjGmWV5QjSk0= k8s.io/kube-scheduler v0.25.0/go.mod h1:cwiyJeImgFbhmbnImzvuhbiJayNngRNEe3FJkZDPw9Y=
k8s.io/kubelet v0.24.3/go.mod h1:vIdQ8bybBvLeMysTyj37QZNKNnCGVfWqpbsLaMT7wTE= k8s.io/kubectl v0.25.0/go.mod h1:n16ULWsOl2jmQpzt2o7Dud1t4o0+Y186ICb4O+GwKAU=
k8s.io/kubernetes v1.24.3 h1:RVuivOFTujzUDYZV8UFXCeD05US8DowBbxV+97JWEFg= k8s.io/kubelet v0.25.0/go.mod h1:J6aQxrZdSsGPrskYrhZdEn6PCnGha+GNvF0g9aWfQnw=
k8s.io/kubernetes v1.24.3/go.mod h1:8e8maMiZzBR2/8Po5Uulx+MXZUYJuN3vtKwD4Ct1Xi0= k8s.io/kubernetes v1.25.0 h1:NwTRyLrdXTORd5V7DLlUltxDbl/KZjYDiRgwI+pBYGE=
k8s.io/legacy-cloud-providers v0.24.3/go.mod h1:G548jzl58czqsrebwY1XXFKEkCEcJhX8tnPUCFv/uMo= k8s.io/kubernetes v1.25.0/go.mod h1:UdtILd5Zg1vGZvShiO1EYOqmjzM2kZOG1hzwQnM5JxY=
k8s.io/metrics v0.24.3/go.mod h1:p1M0lhMySWfhISkSd3HEj8xIgrVnJTK3PPhFq2rA3To= k8s.io/legacy-cloud-providers v0.25.0/go.mod h1:bnmUgHHeBmK3M9JgQzu+ne6UCUVURDzkpF0Y7VeypVE=
k8s.io/mount-utils v0.24.3/go.mod h1:XrSqB3a2e8sq+aU+rlbcBtQ3EgcuDk5RP9ZsGxjoDrI= k8s.io/metrics v0.25.0/go.mod h1:HZZrbhuRX+fsDcRc3u59o2FbrKhqD67IGnoFECNmovc=
k8s.io/pod-security-admission v0.24.3/go.mod h1:l862a6t98GO7IIIGIe/lh01TTq9fWu6ylTb7CLDrXkY= k8s.io/mount-utils v0.25.0/go.mod h1:WTYq8Ev/JrnkqK2h1jFUnC8qWGuqzMb9XDC+Lu3WNU0=
k8s.io/sample-apiserver v0.24.3/go.mod h1:ZDr71tBj39HgTEFPugVn5v32aZ5z7XCu2kLWoygiBp0= k8s.io/pod-security-admission v0.25.0/go.mod h1:b/UC586Th2LijoNV+ssyyAryUvmaTrEWms5ZzBEkVsA=
k8s.io/sample-apiserver v0.25.0/go.mod h1:Wyy/yKmXCrWLcc+082Vsn6fxAuwraRw5FQpekHg3go8=
k8s.io/system-validators v1.7.0/go.mod h1:gP1Ky+R9wtrSiFbrpEPwWMeYz9yqyy1S/KOh0Vci7WI= k8s.io/system-validators v1.7.0/go.mod h1:gP1Ky+R9wtrSiFbrpEPwWMeYz9yqyy1S/KOh0Vci7WI=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
@@ -1194,16 +1248,18 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.32/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s=
sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= sigs.k8s.io/kustomize/cmd/config v0.10.9/go.mod h1:T0s850zPV3wKfBALA0dyeP/K74jlJcoP8Pr9ZWwE3MQ=
sigs.k8s.io/kustomize/kustomize/v4 v4.5.7/go.mod h1:VSNKEH9D9d9bLiWEGbS6Xbg/Ih0tgQalmPvntzRxZ/Q=
sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

View File

@@ -217,7 +217,9 @@ const (
// See VolumeExpansion for details. // See VolumeExpansion for details.
ControllerServiceCapability_RPC_EXPAND_VOLUME ControllerServiceCapability_RPC_Type = 9 ControllerServiceCapability_RPC_EXPAND_VOLUME ControllerServiceCapability_RPC_Type = 9
// Indicates the SP supports the // Indicates the SP supports the
// ListVolumesResponse.entry.published_nodes field // ListVolumesResponse.entry.published_node_ids field and the
// ControllerGetVolumeResponse.published_node_ids field.
// The SP MUST also support PUBLISH_UNPUBLISH_VOLUME.
ControllerServiceCapability_RPC_LIST_VOLUMES_PUBLISHED_NODES ControllerServiceCapability_RPC_Type = 10 ControllerServiceCapability_RPC_LIST_VOLUMES_PUBLISHED_NODES ControllerServiceCapability_RPC_Type = 10
// Indicates that the Controller service can report volume // Indicates that the Controller service can report volume
// conditions. // conditions.
@@ -2678,7 +2680,7 @@ type ControllerGetVolumeResponse_VolumeStatus struct {
// A list of all the `node_id` of nodes that this volume is // A list of all the `node_id` of nodes that this volume is
// controller published on. // controller published on.
// This field is OPTIONAL. // This field is OPTIONAL.
// This field MUST be specified if the PUBLISH_UNPUBLISH_VOLUME // This field MUST be specified if the LIST_VOLUMES_PUBLISHED_NODES
// controller capability is supported. // controller capability is supported.
// published_node_ids MAY include nodes not published to or // published_node_ids MAY include nodes not published to or
// reported by the SP. The CO MUST be resilient to that. // reported by the SP. The CO MUST be resilient to that.
@@ -5058,245 +5060,245 @@ func init() {
} }
var fileDescriptor_9cdb00adce470e01 = []byte{ var fileDescriptor_9cdb00adce470e01 = []byte{
// 3797 bytes of a gzipped FileDescriptorProto // 3802 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x3b, 0x4b, 0x6c, 0x1b, 0x49, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x3b, 0x4b, 0x6c, 0x23, 0x47,
0x76, 0x6a, 0xfe, 0x24, 0x3d, 0x4a, 0x32, 0x5d, 0xfa, 0x98, 0x6e, 0x49, 0x96, 0xdc, 0x1e, 0x7b, 0x76, 0x6a, 0xfe, 0x24, 0x3d, 0x4a, 0x1a, 0xaa, 0x28, 0x69, 0x38, 0x2d, 0x69, 0xa4, 0xe9, 0xf1,
0x65, 0x8f, 0x4d, 0xaf, 0xb5, 0x63, 0x23, 0x23, 0x7b, 0x76, 0x87, 0xa4, 0x68, 0x89, 0x6b, 0x8a, 0x78, 0xe5, 0xf1, 0x0c, 0x67, 0xad, 0xb5, 0x8d, 0x58, 0x1e, 0xef, 0x9a, 0xa4, 0x38, 0x12, 0x77,
0xd4, 0x34, 0x29, 0x7b, 0xed, 0x64, 0xd0, 0xd3, 0x22, 0x4b, 0x74, 0x63, 0xc8, 0x6e, 0x4e, 0x77, 0x28, 0x52, 0x6e, 0x52, 0x33, 0x3b, 0x93, 0x18, 0xed, 0x16, 0x59, 0xe2, 0x34, 0x4c, 0x76, 0xd3,
0x53, 0x91, 0xe6, 0x92, 0x20, 0x41, 0x0e, 0x41, 0x2e, 0xb9, 0xed, 0xe4, 0xb6, 0x48, 0xf6, 0x98, 0xdd, 0x4d, 0x45, 0xf2, 0x25, 0x41, 0x82, 0x1c, 0x82, 0x5c, 0x72, 0x5b, 0xe7, 0xb6, 0x48, 0xf6,
0xc5, 0x22, 0x08, 0x82, 0x1c, 0x03, 0xe4, 0x18, 0x20, 0x9b, 0xdc, 0x12, 0xe4, 0xb2, 0xb7, 0x20, 0x98, 0xc5, 0x22, 0x08, 0x82, 0x1c, 0x03, 0xe4, 0x18, 0x20, 0x9b, 0xdc, 0x12, 0xe4, 0xb2, 0x87,
0x58, 0x24, 0xc0, 0x5c, 0x72, 0xc9, 0x21, 0x08, 0xba, 0xaa, 0xba, 0xd9, 0x5f, 0x7e, 0x2c, 0x19, 0x00, 0x39, 0x2c, 0x12, 0xc0, 0x97, 0x5c, 0x72, 0x08, 0x82, 0xae, 0xaa, 0x6e, 0xf6, 0x97, 0x9f,
0x73, 0xc8, 0x49, 0xec, 0x57, 0xef, 0xbd, 0x7a, 0x55, 0xf5, 0xde, 0xab, 0xf7, 0x29, 0xc1, 0xe3, 0x91, 0x06, 0x3e, 0xe4, 0x24, 0xf6, 0xab, 0xf7, 0x5e, 0xbd, 0xaa, 0x7a, 0xef, 0xd5, 0xfb, 0x94,
0xb6, 0x62, 0xbe, 0xed, 0x1f, 0xe7, 0x9a, 0x5a, 0xf7, 0x61, 0x53, 0x53, 0x4d, 0x59, 0x51, 0xb1, 0xe0, 0x83, 0x8e, 0x62, 0xbe, 0x1a, 0x9c, 0xe6, 0x5b, 0x5a, 0xef, 0x51, 0x4b, 0x53, 0x4d, 0x59,
0xfe, 0xc0, 0x30, 0x35, 0x5d, 0x6e, 0xe3, 0x07, 0x8a, 0x6a, 0x62, 0xfd, 0x44, 0x6e, 0xe2, 0x87, 0x51, 0xb1, 0xfe, 0xd0, 0x30, 0x35, 0x5d, 0xee, 0xe0, 0x87, 0x8a, 0x6a, 0x62, 0xfd, 0x4c, 0x6e,
0x46, 0x0f, 0x37, 0x1f, 0x36, 0x0d, 0x25, 0xd7, 0xd3, 0x35, 0x53, 0x43, 0x29, 0xeb, 0xe7, 0xe9, 0xe1, 0x47, 0x46, 0x1f, 0xb7, 0x1e, 0xb5, 0x0c, 0x25, 0xdf, 0xd7, 0x35, 0x53, 0x43, 0x29, 0xeb,
0x23, 0x7e, 0xb3, 0xad, 0x69, 0xed, 0x0e, 0x7e, 0x48, 0xa0, 0xc7, 0xfd, 0x93, 0x87, 0x2d, 0x6c, 0xe7, 0xf9, 0x7b, 0xfc, 0x76, 0x47, 0xd3, 0x3a, 0x5d, 0xfc, 0x88, 0x40, 0x4f, 0x07, 0x67, 0x8f,
0x34, 0x75, 0xa5, 0x67, 0x6a, 0x3a, 0xc5, 0xe4, 0x37, 0xfc, 0x18, 0xa6, 0xd2, 0xc5, 0x86, 0x29, 0xda, 0xd8, 0x68, 0xe9, 0x4a, 0xdf, 0xd4, 0x74, 0x8a, 0xc9, 0x6f, 0xf9, 0x31, 0x4c, 0xa5, 0x87,
0x77, 0x7b, 0x0c, 0xe1, 0x86, 0x1f, 0xe1, 0x77, 0x75, 0xb9, 0xd7, 0xc3, 0xba, 0x41, 0xc7, 0x85, 0x0d, 0x53, 0xee, 0xf5, 0x19, 0xc2, 0x6d, 0x3f, 0xc2, 0xef, 0xea, 0x72, 0xbf, 0x8f, 0x75, 0x83,
0x15, 0x58, 0xda, 0xc3, 0xe6, 0x61, 0xa7, 0xdf, 0x56, 0xd4, 0xb2, 0x7a, 0xa2, 0x89, 0xf8, 0xab, 0x8e, 0x0b, 0x6b, 0xb0, 0x72, 0x80, 0xcd, 0xe3, 0xee, 0xa0, 0xa3, 0xa8, 0x15, 0xf5, 0x4c, 0x13,
0x3e, 0x36, 0x4c, 0xe1, 0x5f, 0x39, 0x58, 0xf6, 0x0d, 0x18, 0x3d, 0x4d, 0x35, 0x30, 0x42, 0x90, 0xf1, 0x57, 0x03, 0x6c, 0x98, 0xc2, 0xbf, 0x72, 0xb0, 0xea, 0x1b, 0x30, 0xfa, 0x9a, 0x6a, 0x60,
0x50, 0xe5, 0x2e, 0xce, 0x72, 0x9b, 0xdc, 0xd6, 0xac, 0x48, 0x7e, 0xa3, 0xdb, 0xb0, 0x70, 0x8a, 0x84, 0x20, 0xa1, 0xca, 0x3d, 0x9c, 0xe3, 0xb6, 0xb9, 0x9d, 0x79, 0x91, 0xfc, 0x46, 0xf7, 0x60,
0xd5, 0x96, 0xa6, 0x4b, 0xa7, 0x58, 0x37, 0x14, 0x4d, 0xcd, 0xc6, 0xc8, 0xe8, 0x3c, 0x85, 0xbe, 0xe9, 0x1c, 0xab, 0x6d, 0x4d, 0x97, 0xce, 0xb1, 0x6e, 0x28, 0x9a, 0x9a, 0x8b, 0x91, 0xd1, 0x45,
0xa4, 0x40, 0xb4, 0x07, 0x33, 0x5d, 0x59, 0x55, 0x4e, 0xb0, 0x61, 0x66, 0xe3, 0x9b, 0xf1, 0xad, 0x0a, 0x7d, 0x46, 0x81, 0xe8, 0x00, 0xe6, 0x7a, 0xb2, 0xaa, 0x9c, 0x61, 0xc3, 0xcc, 0xc5, 0xb7,
0xf4, 0xf6, 0x87, 0x39, 0xba, 0xd4, 0x5c, 0xe8, 0x5c, 0xb9, 0x03, 0x86, 0x5d, 0x52, 0x4d, 0xfd, 0xe3, 0x3b, 0xe9, 0xdd, 0x77, 0xf3, 0x74, 0xa9, 0xf9, 0xd0, 0xb9, 0xf2, 0x47, 0x0c, 0xbb, 0xac,
0x5c, 0x74, 0x88, 0xf9, 0xa7, 0x30, 0xef, 0x19, 0x42, 0x19, 0x88, 0x7f, 0x89, 0xcf, 0x99, 0x4c, 0x9a, 0xfa, 0xa5, 0xe8, 0x10, 0xf3, 0x1f, 0xc3, 0xa2, 0x67, 0x08, 0x65, 0x20, 0xfe, 0x25, 0xbe,
0xd6, 0x4f, 0xb4, 0x04, 0xc9, 0x53, 0xb9, 0xd3, 0xc7, 0x4c, 0x12, 0xfa, 0xb1, 0x13, 0xfb, 0x2d, 0x64, 0x32, 0x59, 0x3f, 0xd1, 0x0a, 0x24, 0xcf, 0xe5, 0xee, 0x00, 0x33, 0x49, 0xe8, 0xc7, 0x5e,
0x4e, 0xb8, 0x01, 0x6b, 0xce, 0x6c, 0x45, 0xb9, 0x27, 0x1f, 0x2b, 0x1d, 0xc5, 0x54, 0xb0, 0x61, 0xec, 0xb7, 0x38, 0xe1, 0x36, 0x6c, 0x38, 0xb3, 0x95, 0xe4, 0xbe, 0x7c, 0xaa, 0x74, 0x15, 0x53,
0x2f, 0xfd, 0x73, 0x58, 0x8f, 0x18, 0x67, 0x3b, 0xf0, 0x0c, 0xe6, 0x9a, 0x2e, 0x78, 0x96, 0x23, 0xc1, 0x86, 0xbd, 0xf4, 0xcf, 0x61, 0x33, 0x62, 0x9c, 0xed, 0xc0, 0x63, 0x58, 0x68, 0xb9, 0xe0,
0x4b, 0xc9, 0xda, 0x4b, 0xf1, 0x51, 0x9e, 0x8b, 0x1e, 0x6c, 0xe1, 0x57, 0x71, 0xc8, 0xf8, 0x51, 0x39, 0x8e, 0x2c, 0x25, 0x67, 0x2f, 0xc5, 0x47, 0x79, 0x29, 0x7a, 0xb0, 0x85, 0x5f, 0xc5, 0x21,
0xd0, 0x33, 0x98, 0x36, 0xb0, 0x7e, 0xaa, 0x34, 0xe9, 0xbe, 0xa6, 0xb7, 0x37, 0xa3, 0xb8, 0xe5, 0xe3, 0x47, 0x41, 0x8f, 0x61, 0xd6, 0xc0, 0xfa, 0xb9, 0xd2, 0xa2, 0xfb, 0x9a, 0xde, 0xdd, 0x8e,
0xea, 0x14, 0x6f, 0x7f, 0x4a, 0xb4, 0x49, 0xd0, 0x11, 0x64, 0x4e, 0xb5, 0x4e, 0xbf, 0x8b, 0x25, 0xe2, 0x96, 0x6f, 0x50, 0xbc, 0xc3, 0x19, 0xd1, 0x26, 0x41, 0x27, 0x90, 0x39, 0xd7, 0xba, 0x83,
0x7c, 0xd6, 0x93, 0x55, 0xe7, 0x00, 0xd2, 0xdb, 0x5b, 0x91, 0x6c, 0x5e, 0x12, 0x82, 0x92, 0x8d, 0x1e, 0x96, 0xf0, 0x45, 0x5f, 0x56, 0x9d, 0x03, 0x48, 0xef, 0xee, 0x44, 0xb2, 0x79, 0x46, 0x08,
0xbf, 0x3f, 0x25, 0x5e, 0x39, 0xf5, 0x82, 0xf8, 0x9f, 0x72, 0x30, 0xcd, 0x66, 0x43, 0x1f, 0x43, 0xca, 0x36, 0xfe, 0xe1, 0x8c, 0x78, 0xe3, 0xdc, 0x0b, 0xe2, 0x7f, 0xca, 0xc1, 0x2c, 0x9b, 0x0d,
0xc2, 0x3c, 0xef, 0x51, 0xe9, 0x16, 0xb6, 0x6f, 0x8f, 0x92, 0x2e, 0xd7, 0x38, 0xef, 0x61, 0x91, 0x7d, 0x04, 0x09, 0xf3, 0xb2, 0x4f, 0xa5, 0x5b, 0xda, 0xbd, 0x37, 0x4e, 0xba, 0x7c, 0xf3, 0xb2,
0x90, 0x08, 0x9f, 0x41, 0xc2, 0xfa, 0x42, 0x69, 0x98, 0x3e, 0xaa, 0xbe, 0xa8, 0xd6, 0x5e, 0x55, 0x8f, 0x45, 0x42, 0x22, 0x7c, 0x06, 0x09, 0xeb, 0x0b, 0xa5, 0x61, 0xf6, 0xa4, 0xf6, 0xb4, 0x56,
0x33, 0x53, 0x68, 0x05, 0x50, 0xb1, 0x56, 0x6d, 0x88, 0xb5, 0x4a, 0xa5, 0x24, 0x4a, 0xf5, 0x92, 0x7f, 0x5e, 0xcb, 0xcc, 0xa0, 0x35, 0x40, 0xa5, 0x7a, 0xad, 0x29, 0xd6, 0xab, 0xd5, 0xb2, 0x28,
0xf8, 0xb2, 0x5c, 0x2c, 0x65, 0x38, 0xf4, 0x01, 0x6c, 0xbe, 0xac, 0x55, 0x8e, 0x0e, 0x4a, 0x52, 0x35, 0xca, 0xe2, 0xb3, 0x4a, 0xa9, 0x9c, 0xe1, 0xd0, 0x5b, 0xb0, 0xfd, 0xac, 0x5e, 0x3d, 0x39,
0xbe, 0x58, 0x2c, 0xd5, 0xeb, 0xe5, 0x42, 0xb9, 0x52, 0x6e, 0xbc, 0x96, 0x8a, 0xb5, 0x6a, 0xbd, 0x2a, 0x4b, 0x85, 0x52, 0xa9, 0xdc, 0x68, 0x54, 0x8a, 0x95, 0x6a, 0xa5, 0xf9, 0x42, 0x2a, 0xd5,
0x21, 0xe6, 0xcb, 0xd5, 0x46, 0x3d, 0x13, 0xe3, 0xff, 0x80, 0x83, 0x2b, 0xbe, 0x05, 0xa0, 0xbc, 0x6b, 0x8d, 0xa6, 0x58, 0xa8, 0xd4, 0x9a, 0x8d, 0x4c, 0x8c, 0xff, 0x03, 0x0e, 0x6e, 0xf8, 0x16,
0x47, 0xc2, 0x07, 0xe3, 0x2e, 0xdc, 0x2d, 0xe9, 0xfd, 0x30, 0x49, 0x01, 0x52, 0xb5, 0x6a, 0xa5, 0x80, 0x0a, 0x1e, 0x09, 0x1f, 0x4e, 0xba, 0x70, 0xb7, 0xa4, 0x0f, 0xc2, 0x24, 0x05, 0x48, 0xd5,
0x5c, 0xb5, 0xa4, 0x4b, 0xc3, 0x74, 0xed, 0xf9, 0x73, 0xf2, 0x11, 0x2b, 0xa4, 0xe8, 0x84, 0xc2, 0x6b, 0xd5, 0x4a, 0xcd, 0x92, 0x2e, 0x0d, 0xb3, 0xf5, 0x27, 0x4f, 0xc8, 0x47, 0xac, 0x98, 0xa2,
0x02, 0xcc, 0x1d, 0xea, 0xda, 0x31, 0xb6, 0xf5, 0x27, 0x0f, 0xf3, 0xec, 0x9b, 0xe9, 0xcb, 0xf7, 0x13, 0x0a, 0x4b, 0xb0, 0x70, 0xac, 0x6b, 0xa7, 0xd8, 0xd6, 0x9f, 0x02, 0x2c, 0xb2, 0x6f, 0xa6,
0x21, 0xa9, 0x63, 0xb9, 0x75, 0xce, 0x8e, 0x96, 0xcf, 0x51, 0x9b, 0xcc, 0xd9, 0x36, 0x99, 0x2b, 0x2f, 0xdf, 0x87, 0xa4, 0x8e, 0xe5, 0xf6, 0x25, 0x3b, 0x5a, 0x3e, 0x4f, 0x6d, 0x32, 0x6f, 0xdb,
0x68, 0x5a, 0xe7, 0xa5, 0xa5, 0x9f, 0x22, 0x45, 0x14, 0xbe, 0x4d, 0xc0, 0x62, 0x51, 0xc7, 0xb2, 0x64, 0xbe, 0xa8, 0x69, 0xdd, 0x67, 0x96, 0x7e, 0x8a, 0x14, 0x51, 0xf8, 0x36, 0x01, 0xd9, 0x92,
0x89, 0xa9, 0xb4, 0x8c, 0x75, 0xa8, 0xed, 0x3d, 0x83, 0x05, 0x4b, 0xbf, 0x9a, 0x8a, 0x79, 0x2e, 0x8e, 0x65, 0x13, 0x53, 0x69, 0x19, 0xeb, 0x50, 0xdb, 0x7b, 0x0c, 0x4b, 0x96, 0x7e, 0xb5, 0x14,
0xe9, 0xb2, 0xda, 0xc6, 0xec, 0xe8, 0x97, 0xed, 0x1d, 0x28, 0xb2, 0x51, 0xd1, 0x1a, 0x14, 0xe7, 0xf3, 0x52, 0xd2, 0x65, 0xb5, 0x83, 0xd9, 0xd1, 0xaf, 0xda, 0x3b, 0x50, 0x62, 0xa3, 0xa2, 0x35,
0x9b, 0xee, 0x4f, 0x54, 0x86, 0x45, 0xa6, 0x3a, 0x1e, 0x95, 0x8e, 0x7b, 0x55, 0x9a, 0x4a, 0xe1, 0x28, 0x2e, 0xb6, 0xdc, 0x9f, 0xa8, 0x02, 0x59, 0xa6, 0x3a, 0x1e, 0x95, 0x8e, 0x7b, 0x55, 0x9a,
0x52, 0x69, 0x74, 0xea, 0x85, 0x28, 0xd8, 0x40, 0x2f, 0x00, 0x7a, 0xb2, 0x2e, 0x77, 0xb1, 0x89, 0x4a, 0xe1, 0x52, 0x69, 0x74, 0xee, 0x85, 0x28, 0xd8, 0x40, 0x4f, 0x01, 0xfa, 0xb2, 0x2e, 0xf7,
0x75, 0x23, 0x9b, 0xf0, 0xda, 0x77, 0xc8, 0x6a, 0x72, 0x87, 0x0e, 0x36, 0xb5, 0x6f, 0x17, 0x39, 0xb0, 0x89, 0x75, 0x23, 0x97, 0xf0, 0xda, 0x77, 0xc8, 0x6a, 0xf2, 0xc7, 0x0e, 0x36, 0xb5, 0x6f,
0xda, 0xb3, 0x0c, 0xa2, 0xa9, 0x63, 0xd3, 0xc8, 0x26, 0x09, 0xa7, 0xad, 0x61, 0x9c, 0xea, 0x14, 0x17, 0x39, 0x3a, 0xb0, 0x0c, 0xa2, 0xa5, 0x63, 0xd3, 0xc8, 0x25, 0x09, 0xa7, 0x9d, 0x51, 0x9c,
0x95, 0xb0, 0x29, 0xc4, 0xbf, 0x29, 0x70, 0xa2, 0x4d, 0x8d, 0x6a, 0xb0, 0x6c, 0x2f, 0x50, 0x53, 0x1a, 0x14, 0x95, 0xb0, 0x29, 0xc6, 0xbf, 0x29, 0x72, 0xa2, 0x4d, 0x8d, 0xea, 0xb0, 0x6a, 0x2f,
0x4d, 0xac, 0x9a, 0x92, 0xa1, 0xf5, 0xf5, 0x26, 0xce, 0xa6, 0xc8, 0x2e, 0xad, 0xfa, 0x96, 0x48, 0x50, 0x53, 0x4d, 0xac, 0x9a, 0x92, 0xa1, 0x0d, 0xf4, 0x16, 0xce, 0xa5, 0xc8, 0x2e, 0xad, 0xfb,
0x71, 0xea, 0x04, 0x45, 0x64, 0x5b, 0xe3, 0x01, 0xa2, 0x37, 0xc0, 0xcb, 0xcd, 0x26, 0x36, 0x0c, 0x96, 0x48, 0x71, 0x1a, 0x04, 0x45, 0x64, 0x5b, 0xe3, 0x01, 0xa2, 0x97, 0xc0, 0xcb, 0xad, 0x16,
0x85, 0xee, 0x85, 0xa4, 0xe3, 0xaf, 0xfa, 0x8a, 0x8e, 0xbb, 0x58, 0x35, 0x8d, 0xec, 0xb4, 0x97, 0x36, 0x0c, 0x85, 0xee, 0x85, 0xa4, 0xe3, 0xaf, 0x06, 0x8a, 0x8e, 0x7b, 0x58, 0x35, 0x8d, 0xdc,
0x6b, 0x43, 0xeb, 0x69, 0x1d, 0xad, 0x7d, 0x2e, 0x0e, 0x70, 0xc4, 0xeb, 0x1e, 0x72, 0xd7, 0x88, 0xac, 0x97, 0x6b, 0x53, 0xeb, 0x6b, 0x5d, 0xad, 0x73, 0x29, 0x0e, 0x71, 0xc4, 0x5b, 0x1e, 0x72,
0xc1, 0x7f, 0x02, 0x57, 0x7c, 0x9b, 0x32, 0x89, 0x67, 0xe3, 0x77, 0x60, 0xce, 0xbd, 0x13, 0x13, 0xd7, 0x88, 0xc1, 0x7f, 0x02, 0x37, 0x7c, 0x9b, 0x32, 0x8d, 0x67, 0xe3, 0xf7, 0x60, 0xc1, 0xbd,
0x79, 0xc5, 0x3f, 0x89, 0xc1, 0x62, 0xc8, 0x1e, 0xa0, 0x7d, 0x98, 0x31, 0x54, 0xb9, 0x67, 0xbc, 0x13, 0x53, 0x79, 0xc5, 0x3f, 0x89, 0x41, 0x36, 0x64, 0x0f, 0xd0, 0x21, 0xcc, 0x19, 0xaa, 0xdc,
0xd5, 0x4c, 0xa6, 0xbf, 0xf7, 0x86, 0x6c, 0x59, 0xae, 0xce, 0x70, 0xe9, 0xe7, 0xfe, 0x94, 0xe8, 0x37, 0x5e, 0x69, 0x26, 0xd3, 0xdf, 0xfb, 0x23, 0xb6, 0x2c, 0xdf, 0x60, 0xb8, 0xf4, 0xf3, 0x70,
0x50, 0xa3, 0x02, 0xa4, 0xe8, 0x7e, 0xfa, 0x7d, 0x53, 0x18, 0x1f, 0x0a, 0x73, 0xb8, 0x30, 0x4a, 0x46, 0x74, 0xa8, 0x51, 0x11, 0x52, 0x74, 0x3f, 0xfd, 0xbe, 0x29, 0x8c, 0x0f, 0x85, 0x39, 0x5c,
0xfe, 0x11, 0x2c, 0x78, 0x67, 0x40, 0x1b, 0x90, 0xb6, 0x67, 0x90, 0x94, 0x16, 0x5b, 0x2b, 0xd8, 0x18, 0x25, 0xff, 0x1e, 0x2c, 0x79, 0x67, 0x40, 0x5b, 0x90, 0xb6, 0x67, 0x90, 0x94, 0x36, 0x5b,
0xa0, 0x72, 0x8b, 0xff, 0x10, 0xe6, 0xdc, 0xcc, 0xd0, 0x2a, 0xcc, 0x32, 0x85, 0x70, 0xd0, 0x67, 0x2b, 0xd8, 0xa0, 0x4a, 0x9b, 0x7f, 0x17, 0x16, 0xdc, 0xcc, 0xd0, 0x3a, 0xcc, 0x33, 0x85, 0x70,
0x28, 0xa0, 0xdc, 0x72, 0x6c, 0xfa, 0x87, 0xb0, 0xe4, 0xd5, 0x33, 0x66, 0xca, 0x77, 0x9c, 0x35, 0xd0, 0xe7, 0x28, 0xa0, 0xd2, 0x76, 0x6c, 0xfa, 0x87, 0xb0, 0xe2, 0xd5, 0x33, 0x66, 0xca, 0x6f,
0xd0, 0xbd, 0x58, 0xf0, 0xae, 0xc1, 0x96, 0x53, 0xf8, 0x79, 0x12, 0x32, 0x7e, 0xa3, 0x41, 0xcf, 0x3b, 0x6b, 0xa0, 0x7b, 0xb1, 0xe4, 0x5d, 0x83, 0x2d, 0xa7, 0xf0, 0xf3, 0x24, 0x64, 0xfc, 0x46,
0x20, 0x79, 0xdc, 0xd1, 0x9a, 0x5f, 0x32, 0xda, 0x0f, 0xa2, 0xac, 0x2b, 0x57, 0xb0, 0xb0, 0x28, 0x83, 0x1e, 0x43, 0xf2, 0xb4, 0xab, 0xb5, 0xbe, 0x64, 0xb4, 0x6f, 0x45, 0x59, 0x57, 0xbe, 0x68,
0x74, 0x7f, 0x4a, 0xa4, 0x44, 0x16, 0x75, 0x57, 0xeb, 0xab, 0x26, 0xdb, 0xbd, 0x68, 0xea, 0x03, 0x61, 0x51, 0xe8, 0xe1, 0x8c, 0x48, 0x89, 0x2c, 0xea, 0x9e, 0x36, 0x50, 0x4d, 0xb6, 0x7b, 0xd1,
0x0b, 0x6b, 0x40, 0x4d, 0x88, 0xd0, 0x2e, 0xa4, 0xa9, 0xda, 0x49, 0x5d, 0xad, 0x85, 0xb3, 0x71, 0xd4, 0x47, 0x16, 0xd6, 0x90, 0x9a, 0x10, 0xa1, 0x7d, 0x48, 0x53, 0xb5, 0x93, 0x7a, 0x5a, 0x1b,
0xc2, 0xe3, 0x56, 0x24, 0x8f, 0x3c, 0xc1, 0x3d, 0xd0, 0x5a, 0x58, 0x04, 0xd9, 0xf9, 0xcd, 0xcf, 0xe7, 0xe2, 0x84, 0xc7, 0xdd, 0x48, 0x1e, 0x05, 0x82, 0x7b, 0xa4, 0xb5, 0xb1, 0x08, 0xb2, 0xf3,
0x43, 0xda, 0x25, 0x1b, 0xff, 0x35, 0xa4, 0x5d, 0x93, 0xa1, 0x6b, 0x30, 0x7d, 0x62, 0x48, 0x8e, 0x9b, 0x5f, 0x84, 0xb4, 0x4b, 0x36, 0xfe, 0x6b, 0x48, 0xbb, 0x26, 0x43, 0x37, 0x61, 0xf6, 0xcc,
0x13, 0x9e, 0x15, 0x53, 0x27, 0x06, 0xf1, 0xa7, 0x1b, 0x90, 0x26, 0x52, 0x48, 0x27, 0x1d, 0xb9, 0x90, 0x1c, 0x27, 0x3c, 0x2f, 0xa6, 0xce, 0x0c, 0xe2, 0x4f, 0xb7, 0x20, 0x4d, 0xa4, 0x90, 0xce,
0x6d, 0x64, 0x63, 0x9b, 0x71, 0xeb, 0x8c, 0x08, 0xe8, 0xb9, 0x05, 0x41, 0x8f, 0x80, 0x39, 0x14, 0xba, 0x72, 0xc7, 0xc8, 0xc5, 0xb6, 0xe3, 0xd6, 0x19, 0x11, 0xd0, 0x13, 0x0b, 0x82, 0xde, 0x03,
0x89, 0xe2, 0xb5, 0x75, 0xad, 0xdf, 0x23, 0x42, 0xce, 0x16, 0xe2, 0x3f, 0x2b, 0x70, 0x22, 0xbb, 0xe6, 0x50, 0x24, 0x8a, 0xd7, 0xd1, 0xb5, 0x41, 0x9f, 0x08, 0x39, 0x5f, 0x8c, 0xff, 0xac, 0xc8,
0xdf, 0xc8, 0x6c, 0x7b, 0xd6, 0x20, 0xff, 0xd7, 0x31, 0x80, 0x81, 0x94, 0xe8, 0x19, 0x24, 0xc8, 0x89, 0xec, 0x7e, 0x23, 0xb3, 0x1d, 0x58, 0x83, 0xfc, 0x5f, 0xc7, 0x00, 0x86, 0x52, 0xa2, 0xc7,
0xc2, 0xa8, 0xf7, 0xdf, 0x1a, 0x63, 0x61, 0x39, 0xb2, 0x3a, 0x42, 0x25, 0xfc, 0x3b, 0x07, 0x09, 0x90, 0x20, 0x0b, 0xa3, 0xde, 0x7f, 0x67, 0x82, 0x85, 0xe5, 0xc9, 0xea, 0x08, 0x95, 0xf0, 0x1f,
0xc2, 0xc6, 0x7f, 0x47, 0xd5, 0xcb, 0xd5, 0xbd, 0x4a, 0x49, 0xaa, 0xd6, 0x76, 0x4b, 0xd2, 0x2b, 0x1c, 0x24, 0x08, 0x1b, 0xff, 0x1d, 0xd5, 0xa8, 0xd4, 0x0e, 0xaa, 0x65, 0xa9, 0x56, 0xdf, 0x2f,
0xb1, 0xdc, 0x28, 0x89, 0x19, 0x0e, 0xad, 0xc2, 0x35, 0x37, 0x5c, 0x2c, 0xe5, 0x77, 0x4b, 0xa2, 0x4b, 0xcf, 0xc5, 0x4a, 0xb3, 0x2c, 0x66, 0x38, 0xb4, 0x0e, 0x37, 0xdd, 0x70, 0xb1, 0x5c, 0xd8,
0x54, 0xab, 0x56, 0x5e, 0x67, 0x62, 0x88, 0x87, 0x95, 0x83, 0xa3, 0x4a, 0xa3, 0x1c, 0x1c, 0x8b, 0x2f, 0x8b, 0x52, 0xbd, 0x56, 0x7d, 0x91, 0x89, 0x21, 0x1e, 0xd6, 0x8e, 0x4e, 0xaa, 0xcd, 0x4a,
0xa3, 0x35, 0xc8, 0xba, 0xc6, 0x18, 0x0f, 0xc6, 0x36, 0x61, 0xb1, 0x75, 0x8d, 0xd2, 0x9f, 0x6c, 0x70, 0x2c, 0x8e, 0x36, 0x20, 0xe7, 0x1a, 0x63, 0x3c, 0x18, 0xdb, 0x84, 0xc5, 0xd6, 0x35, 0x4a,
0x30, 0x89, 0x04, 0xb8, 0xee, 0x9e, 0xd3, 0x4b, 0x9b, 0xe2, 0xad, 0x4d, 0x42, 0x37, 0x21, 0xeb, 0x7f, 0xb2, 0xc1, 0x24, 0x12, 0xe0, 0x96, 0x7b, 0x4e, 0x2f, 0x6d, 0x8a, 0xb7, 0x36, 0x09, 0xdd,
0xc6, 0xf1, 0x70, 0x98, 0x26, 0x28, 0x85, 0x79, 0x47, 0x0d, 0x88, 0x9a, 0xbf, 0x82, 0x79, 0xcf, 0x81, 0x9c, 0x1b, 0xc7, 0xc3, 0x61, 0x96, 0xa0, 0x14, 0x17, 0x1d, 0x35, 0x20, 0x6a, 0xfe, 0x1c,
0xed, 0x60, 0x05, 0x72, 0xcc, 0x9d, 0xb5, 0xa4, 0xe3, 0x73, 0x93, 0x04, 0x37, 0xdc, 0x56, 0x5c, 0x16, 0x3d, 0xb7, 0x83, 0x15, 0xc8, 0x31, 0x77, 0xd6, 0x96, 0x4e, 0x2f, 0x4d, 0x12, 0xdc, 0x70,
0x9c, 0xb7, 0xa1, 0x05, 0x0b, 0x68, 0x1d, 0x68, 0x47, 0xe9, 0x2a, 0x26, 0xc3, 0x89, 0x11, 0x1c, 0x3b, 0x71, 0x71, 0xd1, 0x86, 0x16, 0x2d, 0xa0, 0x75, 0xa0, 0x5d, 0xa5, 0xa7, 0x98, 0x0c, 0x27,
0x20, 0x20, 0x82, 0x20, 0xfc, 0x3a, 0x06, 0x29, 0xa6, 0x15, 0xb7, 0x5d, 0xf7, 0x93, 0x87, 0xa5, 0x46, 0x70, 0x80, 0x80, 0x08, 0x82, 0xf0, 0xeb, 0x18, 0xa4, 0x98, 0x56, 0xdc, 0x73, 0xdd, 0x4f,
0x0d, 0xa5, 0x2c, 0x3d, 0x66, 0x19, 0xf3, 0x9a, 0x25, 0xda, 0x87, 0x05, 0xb7, 0x13, 0x3f, 0xb3, 0x1e, 0x96, 0x36, 0x94, 0xb2, 0xf4, 0x98, 0x65, 0xcc, 0x6b, 0x96, 0xe8, 0x10, 0x96, 0xdc, 0x4e,
0xc3, 0xc7, 0x9b, 0xde, 0x73, 0x76, 0x7b, 0x92, 0x33, 0x16, 0x34, 0xce, 0x9f, 0xba, 0x61, 0xa8, 0xfc, 0xc2, 0x0e, 0x1f, 0xef, 0x78, 0xcf, 0xd9, 0xed, 0x49, 0x2e, 0x58, 0xd0, 0xb8, 0x78, 0xee,
0x00, 0x0b, 0xbe, 0x7b, 0x20, 0x31, 0xfa, 0x1e, 0x98, 0x6f, 0x7a, 0x5c, 0x62, 0x1e, 0x16, 0x6d, 0x86, 0xa1, 0x22, 0x2c, 0xf9, 0xee, 0x81, 0xc4, 0xf8, 0x7b, 0x60, 0xb1, 0xe5, 0x71, 0x89, 0x05,
0x17, 0xde, 0xc1, 0x92, 0xc9, 0x5c, 0x3c, 0xbb, 0xa7, 0x32, 0x01, 0xd7, 0x8f, 0x06, 0xc8, 0x36, 0xc8, 0xda, 0x2e, 0xbc, 0x8b, 0x25, 0x93, 0xb9, 0x78, 0x76, 0x4f, 0x65, 0x02, 0xae, 0x1f, 0x0d,
0x8c, 0xff, 0x14, 0x50, 0x50, 0xd6, 0x89, 0xfc, 0x75, 0x1f, 0x16, 0x43, 0x2e, 0x17, 0x94, 0x83, 0x91, 0x6d, 0x18, 0xff, 0x29, 0xa0, 0xa0, 0xac, 0x53, 0xf9, 0xeb, 0x01, 0x64, 0x43, 0x2e, 0x17,
0x59, 0x72, 0x54, 0x86, 0x62, 0x62, 0x16, 0x98, 0x06, 0x25, 0x1a, 0xa0, 0x58, 0xf8, 0x3d, 0x1d, 0x94, 0x87, 0x79, 0x72, 0x54, 0x86, 0x62, 0x62, 0x16, 0x98, 0x06, 0x25, 0x1a, 0xa2, 0x58, 0xf8,
0x9f, 0x60, 0x5d, 0xc7, 0x2d, 0x62, 0x98, 0xa1, 0xf8, 0x0e, 0x8a, 0xf0, 0x87, 0x1c, 0xcc, 0xd8, 0x7d, 0x1d, 0x9f, 0x61, 0x5d, 0xc7, 0x6d, 0x62, 0x98, 0xa1, 0xf8, 0x0e, 0x8a, 0xf0, 0x87, 0x1c,
0x70, 0xb4, 0x03, 0x33, 0x06, 0x6e, 0xd3, 0x8b, 0x8f, 0xce, 0x75, 0xc3, 0x4f, 0x9b, 0xab, 0x33, 0xcc, 0xd9, 0x70, 0xb4, 0x07, 0x73, 0x06, 0xee, 0xd0, 0x8b, 0x8f, 0xce, 0x75, 0xdb, 0x4f, 0x9b,
0x04, 0x16, 0xc2, 0xdb, 0xf8, 0x56, 0x08, 0xef, 0x19, 0x9a, 0x68, 0xf1, 0x7f, 0xcb, 0xc1, 0xe2, 0x6f, 0x30, 0x04, 0x16, 0xc2, 0xdb, 0xf8, 0x56, 0x08, 0xef, 0x19, 0x9a, 0x6a, 0xf1, 0x7f, 0xcb,
0x2e, 0xee, 0x60, 0x7f, 0x7c, 0x34, 0xcc, 0xb7, 0xbb, 0x43, 0x8a, 0x98, 0x37, 0xa4, 0x08, 0x61, 0x41, 0x76, 0x1f, 0x77, 0xb1, 0x3f, 0x3e, 0x1a, 0xe5, 0xdb, 0xdd, 0x21, 0x45, 0xcc, 0x1b, 0x52,
0x35, 0x24, 0xa4, 0xb8, 0xd0, 0x35, 0xbb, 0x02, 0x4b, 0xde, 0xd9, 0xe8, 0xc5, 0x22, 0xfc, 0x57, 0x84, 0xb0, 0x1a, 0x11, 0x52, 0x5c, 0xe9, 0x9a, 0x5d, 0x83, 0x15, 0xef, 0x6c, 0xf4, 0x62, 0x11,
0x1c, 0x6e, 0x58, 0xba, 0xa0, 0x6b, 0x9d, 0x0e, 0xd6, 0x0f, 0xfb, 0xc7, 0x1d, 0xc5, 0x78, 0x3b, 0xfe, 0x2b, 0x0e, 0xb7, 0x2d, 0x5d, 0xd0, 0xb5, 0x6e, 0x17, 0xeb, 0xc7, 0x83, 0xd3, 0xae, 0x62,
0xc1, 0xe2, 0xae, 0xc1, 0xb4, 0xaa, 0xb5, 0x5c, 0xc6, 0x93, 0xb2, 0x3e, 0xcb, 0x2d, 0x54, 0x82, 0xbc, 0x9a, 0x62, 0x71, 0x37, 0x61, 0x56, 0xd5, 0xda, 0x2e, 0xe3, 0x49, 0x59, 0x9f, 0x95, 0x36,
0xab, 0xfe, 0x00, 0xef, 0x9c, 0xb9, 0xff, 0xe8, 0xf0, 0x2e, 0x73, 0xea, 0xbf, 0xbb, 0x78, 0x98, 0x2a, 0xc3, 0xb2, 0x3f, 0xc0, 0xbb, 0x64, 0xee, 0x3f, 0x3a, 0xbc, 0xcb, 0x9c, 0xfb, 0xef, 0x2e,
0xb1, 0x42, 0x53, 0x4d, 0xed, 0x9c, 0x13, 0x8b, 0x99, 0x11, 0x9d, 0x6f, 0x24, 0xfa, 0x63, 0xb5, 0x1e, 0xe6, 0xac, 0xd0, 0x54, 0x53, 0xbb, 0x97, 0xc4, 0x62, 0xe6, 0x44, 0xe7, 0x1b, 0x89, 0xfe,
0x1f, 0x38, 0xb1, 0xda, 0xd0, 0x15, 0x0d, 0x0b, 0xdb, 0xbe, 0x08, 0x58, 0x7c, 0x8a, 0xb0, 0xfe, 0x58, 0xed, 0x07, 0x4e, 0xac, 0x36, 0x72, 0x45, 0xa3, 0xc2, 0xb6, 0x2f, 0x02, 0x16, 0x9f, 0x22,
0x78, 0x4c, 0xd6, 0x23, 0x3d, 0xc1, 0x45, 0x4e, 0xf1, 0x12, 0xcc, 0xf7, 0x1f, 0x38, 0xd8, 0x88, 0xac, 0x3f, 0x9a, 0x90, 0xf5, 0x58, 0x4f, 0x70, 0x95, 0x53, 0xbc, 0x06, 0xf3, 0xfd, 0x07, 0x0e,
0x5c, 0x02, 0x0b, 0x36, 0x5a, 0x70, 0xa5, 0x47, 0x07, 0x9c, 0x4d, 0xa0, 0x56, 0xf6, 0x74, 0xe4, 0xb6, 0x22, 0x97, 0xc0, 0x82, 0x8d, 0x36, 0xdc, 0xe8, 0xd3, 0x01, 0x67, 0x13, 0xa8, 0x95, 0x7d,
0x26, 0xb0, 0xfc, 0x99, 0x41, 0x3d, 0xdb, 0xb0, 0xd0, 0xf3, 0x00, 0xf9, 0x3c, 0x2c, 0x86, 0xa0, 0x3c, 0x76, 0x13, 0x58, 0xfe, 0xcc, 0xa0, 0x9e, 0x6d, 0x58, 0xea, 0x7b, 0x80, 0x7c, 0x01, 0xb2,
0x4d, 0xb4, 0x98, 0xdf, 0x70, 0xb0, 0x39, 0x10, 0xe5, 0x48, 0xed, 0x5d, 0x9e, 0xfa, 0x36, 0x06, 0x21, 0x68, 0x53, 0x2d, 0xe6, 0x37, 0x1c, 0x6c, 0x0f, 0x45, 0x39, 0x51, 0xfb, 0xd7, 0xa7, 0xbe,
0xba, 0x45, 0x5d, 0xfe, 0xe3, 0xe0, 0xda, 0xc3, 0x27, 0x7c, 0x5f, 0x16, 0x7c, 0x0b, 0x6e, 0x0e, 0xcd, 0xa1, 0x6e, 0x51, 0x97, 0xff, 0x41, 0x70, 0xed, 0xe1, 0x13, 0xbe, 0x29, 0x0b, 0xbe, 0x0b,
0x99, 0x9a, 0x99, 0xf3, 0xaf, 0x13, 0x70, 0xf3, 0xa5, 0xdc, 0x51, 0x5a, 0x4e, 0x08, 0x19, 0x52, 0x77, 0x46, 0x4c, 0xcd, 0xcc, 0xf9, 0xd7, 0x09, 0xb8, 0xf3, 0x4c, 0xee, 0x2a, 0x6d, 0x27, 0x84,
0x69, 0x18, 0xbe, 0x25, 0xcd, 0x80, 0x05, 0x50, 0xaf, 0xf5, 0xcc, 0xb1, 0xda, 0x51, 0xfc, 0xc7, 0x0c, 0xa9, 0x34, 0x8c, 0xde, 0x92, 0x56, 0xc0, 0x02, 0xa8, 0xd7, 0x7a, 0xec, 0x58, 0xed, 0x38,
0xb8, 0x0e, 0x2f, 0x31, 0xfd, 0x7b, 0x1d, 0x92, 0xfe, 0x7d, 0x3c, 0xbe, 0xac, 0xc3, 0x92, 0xc1, 0xfe, 0x13, 0x5c, 0x87, 0xd7, 0x98, 0xfe, 0xbd, 0x08, 0x49, 0xff, 0x3e, 0x9a, 0x5c, 0xd6, 0x51,
0x23, 0xbf, 0x83, 0x79, 0x32, 0x3e, 0xdf, 0x21, 0x5a, 0x70, 0x61, 0x2b, 0xfe, 0x2e, 0xf3, 0xb5, 0xc9, 0xe0, 0x89, 0xdf, 0xc1, 0x7c, 0x38, 0x39, 0xdf, 0x11, 0x5a, 0x70, 0x65, 0x2b, 0xfe, 0x2e,
0xbf, 0x4f, 0x80, 0x30, 0x6c, 0xf5, 0xcc, 0x87, 0x88, 0x30, 0xdb, 0xd4, 0xd4, 0x13, 0x45, 0xef, 0xf3, 0xb5, 0xbf, 0x4f, 0x80, 0x30, 0x6a, 0xf5, 0xcc, 0x87, 0x88, 0x30, 0xdf, 0xd2, 0xd4, 0x33,
0xe2, 0x16, 0xcb, 0x3b, 0x3e, 0x1a, 0x67, 0xf3, 0x98, 0x03, 0x29, 0xda, 0xb4, 0xe2, 0x80, 0x0d, 0x45, 0xef, 0xe1, 0x36, 0xcb, 0x3b, 0xde, 0x9f, 0x64, 0xf3, 0x98, 0x03, 0x29, 0xd9, 0xb4, 0xe2,
0xca, 0xc2, 0x74, 0x17, 0x1b, 0x86, 0xdc, 0xb6, 0xc5, 0xb2, 0x3f, 0xf9, 0x5f, 0xc4, 0x61, 0xd6, 0x90, 0x0d, 0xca, 0xc1, 0x6c, 0x0f, 0x1b, 0x86, 0xdc, 0xb1, 0xc5, 0xb2, 0x3f, 0xf9, 0x5f, 0xc4,
0x21, 0x41, 0x6a, 0x40, 0x83, 0xa9, 0xfb, 0xda, 0x7b, 0x17, 0x01, 0xde, 0x5d, 0x99, 0x63, 0xef, 0x61, 0xde, 0x21, 0x41, 0x6a, 0x40, 0x83, 0xa9, 0xfb, 0x3a, 0x78, 0x1d, 0x01, 0x5e, 0x5f, 0x99,
0xa0, 0xcc, 0x2d, 0x8f, 0x32, 0x53, 0x73, 0xd8, 0x7d, 0x27, 0xb1, 0x87, 0xe8, 0xf5, 0x77, 0xae, 0x63, 0xaf, 0xa1, 0xcc, 0x6d, 0x8f, 0x32, 0x53, 0x73, 0xd8, 0x7f, 0x2d, 0xb1, 0x47, 0xe8, 0xf5,
0x80, 0xc2, 0xef, 0x00, 0xaa, 0x28, 0x06, 0xcb, 0xdf, 0x1c, 0xb7, 0x64, 0xa5, 0x6b, 0xf2, 0x99, 0x77, 0xae, 0x80, 0xc2, 0xef, 0x00, 0xaa, 0x2a, 0x06, 0xcb, 0xdf, 0x1c, 0xb7, 0x64, 0xa5, 0x6b,
0x84, 0x55, 0x53, 0x57, 0x58, 0xb8, 0x9e, 0x14, 0xa1, 0x2b, 0x9f, 0x95, 0x28, 0xc4, 0x0a, 0xe9, 0xf2, 0x85, 0x84, 0x55, 0x53, 0x57, 0x58, 0xb8, 0x9e, 0x14, 0xa1, 0x27, 0x5f, 0x94, 0x29, 0xc4,
0x0d, 0x53, 0xd6, 0x4d, 0x45, 0x6d, 0x4b, 0xa6, 0xf6, 0x25, 0x76, 0xca, 0xbd, 0x36, 0xb4, 0x61, 0x0a, 0xe9, 0x0d, 0x53, 0xd6, 0x4d, 0x45, 0xed, 0x48, 0xa6, 0xf6, 0x25, 0x76, 0xca, 0xbd, 0x36,
0x01, 0x85, 0xff, 0x8c, 0xc1, 0xa2, 0x87, 0x3d, 0xd3, 0xc9, 0xa7, 0x30, 0x3d, 0xe0, 0xed, 0x09, 0xb4, 0x69, 0x01, 0x85, 0xff, 0x8c, 0x41, 0xd6, 0xc3, 0x9e, 0xe9, 0xe4, 0xc7, 0x30, 0x3b, 0xe4,
0xe3, 0x43, 0xb0, 0x73, 0x74, 0xdb, 0x6c, 0x0a, 0xb4, 0x0e, 0xa0, 0xe2, 0x33, 0xd3, 0x33, 0xef, 0xed, 0x09, 0xe3, 0x43, 0xb0, 0xf3, 0x74, 0xdb, 0x6c, 0x0a, 0xb4, 0x09, 0xa0, 0xe2, 0x0b, 0xd3,
0xac, 0x05, 0x21, 0x73, 0xf2, 0x7f, 0xc4, 0x39, 0xe9, 0xbe, 0x29, 0x9b, 0x7d, 0x03, 0xdd, 0x07, 0x33, 0xef, 0xbc, 0x05, 0x21, 0x73, 0xf2, 0x7f, 0xc4, 0x39, 0xe9, 0xbe, 0x29, 0x9b, 0x03, 0x03,
0xc4, 0x5c, 0x34, 0x6e, 0x49, 0xec, 0x8e, 0xa1, 0xf3, 0xce, 0x8a, 0x19, 0x67, 0xa4, 0x4a, 0x6e, 0x3d, 0x00, 0xc4, 0x5c, 0x34, 0x6e, 0x4b, 0xec, 0x8e, 0xa1, 0xf3, 0xce, 0x8b, 0x19, 0x67, 0xa4,
0x1b, 0x03, 0xed, 0x39, 0x95, 0xd4, 0xa6, 0xa6, 0xb6, 0x14, 0x73, 0x50, 0x49, 0xbd, 0x16, 0x48, 0x46, 0x6e, 0x1b, 0x03, 0x1d, 0x38, 0x95, 0xd4, 0x96, 0xa6, 0xb6, 0x15, 0x73, 0x58, 0x49, 0xbd,
0x10, 0xe8, 0x30, 0xcd, 0x4f, 0xaf, 0x9c, 0x7a, 0xa1, 0xfc, 0x57, 0x90, 0xa4, 0xc7, 0x31, 0x66, 0x19, 0x48, 0x10, 0xe8, 0x30, 0xcd, 0x4f, 0x6f, 0x9c, 0x7b, 0xa1, 0xfc, 0x57, 0x90, 0xa4, 0xc7,
0xc5, 0x00, 0x7d, 0x0a, 0x29, 0x83, 0x48, 0xec, 0xaf, 0x8e, 0x84, 0xed, 0x89, 0x7b, 0x85, 0x22, 0x31, 0x61, 0xc5, 0x00, 0x7d, 0x0a, 0x29, 0x83, 0x48, 0xec, 0xaf, 0x8e, 0x84, 0xed, 0x89, 0x7b,
0xa3, 0x13, 0x7e, 0x08, 0xfc, 0xe0, 0x62, 0xda, 0xc3, 0xe6, 0xf8, 0xd7, 0xef, 0x8e, 0xb5, 0x06, 0x85, 0x22, 0xa3, 0x13, 0x7e, 0x08, 0xfc, 0xf0, 0x62, 0x3a, 0xc0, 0xe6, 0xe4, 0xd7, 0xef, 0x9e,
0xe1, 0xa7, 0x31, 0x58, 0x0d, 0x65, 0x30, 0x59, 0xed, 0x03, 0xed, 0xfb, 0x56, 0xf2, 0xfd, 0xe0, 0xb5, 0x06, 0xe1, 0xa7, 0x31, 0x58, 0x0f, 0x65, 0x30, 0x5d, 0xed, 0x03, 0x1d, 0xfa, 0x56, 0xf2,
0x8d, 0x1d, 0x60, 0x1e, 0xba, 0x22, 0xfe, 0xf7, 0x2f, 0x76, 0x98, 0x85, 0x89, 0x0f, 0x33, 0x70, 0xfd, 0xe0, 0x8d, 0x1d, 0x60, 0x1e, 0xba, 0x22, 0xfe, 0xf7, 0xaf, 0x76, 0x98, 0xc5, 0xa9, 0x0f,
0x8e, 0x74, 0x67, 0x7e, 0x11, 0x03, 0xb4, 0x87, 0x4d, 0x27, 0x55, 0x66, 0x5b, 0x1a, 0xe1, 0x6f, 0x33, 0x70, 0x8e, 0x74, 0x67, 0x7e, 0x11, 0x03, 0x74, 0x80, 0x4d, 0x27, 0x55, 0x66, 0x5b, 0x1a,
0xb8, 0x77, 0xf0, 0x37, 0x3f, 0xf6, 0xf8, 0x1b, 0xea, 0xb1, 0xee, 0xb9, 0x7a, 0x23, 0xbe, 0xa9, 0xe1, 0x6f, 0xb8, 0xd7, 0xf0, 0x37, 0x3f, 0xf6, 0xf8, 0x1b, 0xea, 0xb1, 0xee, 0xbb, 0x7a, 0x23,
0x87, 0xde, 0x96, 0x11, 0xe9, 0x29, 0x8d, 0xf9, 0xc7, 0x4b, 0x4f, 0x2f, 0xe8, 0x56, 0xfe, 0x83, 0xbe, 0xa9, 0x47, 0xde, 0x96, 0x11, 0xe9, 0x29, 0x8d, 0xf9, 0x27, 0x4b, 0x4f, 0xaf, 0xe8, 0x56,
0x83, 0x45, 0x8f, 0xd0, 0x4c, 0x83, 0x1e, 0x00, 0x92, 0x4f, 0x65, 0xa5, 0x23, 0x5b, 0x82, 0xd9, 0xfe, 0x9d, 0x83, 0xac, 0x47, 0x68, 0xa6, 0x41, 0x0f, 0x01, 0xc9, 0xe7, 0xb2, 0xd2, 0x95, 0x2d,
0xe9, 0x3f, 0x2b, 0x07, 0x5c, 0x75, 0x46, 0x6c, 0x32, 0x74, 0x08, 0x8b, 0x5d, 0xf9, 0x4c, 0xe9, 0xc1, 0xec, 0xf4, 0x9f, 0x95, 0x03, 0x96, 0x9d, 0x11, 0x9b, 0x0c, 0x3d, 0x85, 0x6c, 0x4f, 0xbe,
0xf6, 0xbb, 0x12, 0xdb, 0x67, 0x43, 0xf9, 0xda, 0xae, 0x1e, 0xae, 0x06, 0xaa, 0xe8, 0x65, 0xd5, 0x50, 0x7a, 0x83, 0x9e, 0xc4, 0xf6, 0xd9, 0x50, 0xbe, 0xb6, 0xab, 0x87, 0xeb, 0x81, 0x2a, 0x7a,
0x7c, 0xf2, 0x11, 0x29, 0xa3, 0x53, 0x9b, 0xbc, 0xca, 0x88, 0x99, 0x06, 0x29, 0x5f, 0x63, 0xc2, 0x45, 0x35, 0x3f, 0x7c, 0x9f, 0x96, 0xd1, 0x97, 0x19, 0x1d, 0x53, 0x1e, 0xe5, 0x6b, 0x8c, 0x8e,
0x51, 0x51, 0x03, 0x1c, 0xe3, 0x63, 0x73, 0xa4, 0xc4, 0x03, 0x8e, 0x82, 0xe0, 0x8e, 0x7c, 0xd9, 0x21, 0xdb, 0x53, 0xd4, 0x00, 0xb3, 0xf8, 0x58, 0x66, 0xd4, 0xc0, 0x97, 0x19, 0xf1, 0x90, 0xa3,
0x9a, 0xfd, 0x0d, 0xa5, 0x8e, 0x3b, 0x62, 0x0c, 0xe0, 0xb0, 0xbd, 0xd9, 0x0b, 0x6d, 0x2a, 0xdd, 0x20, 0xb8, 0x83, 0x5e, 0xb6, 0x5c, 0x7f, 0x2f, 0xa9, 0xeb, 0x0e, 0x16, 0x03, 0x38, 0x6c, 0x5b,
0x0a, 0xda, 0x0e, 0xeb, 0xb0, 0x44, 0xf6, 0x97, 0xfe, 0x37, 0xee, 0x36, 0xe3, 0x00, 0x36, 0x7a, 0x0e, 0x42, 0xfb, 0x49, 0x77, 0x83, 0x66, 0xc3, 0x9a, 0x2b, 0x91, 0xad, 0xa5, 0xff, 0x8d, 0xbb,
0x0a, 0x71, 0xbd, 0xd7, 0x64, 0x36, 0xfc, 0xbd, 0x31, 0xf8, 0xe7, 0xc4, 0xc3, 0xe2, 0xfe, 0x94, 0x2d, 0x38, 0x80, 0x8d, 0x3e, 0x86, 0xb8, 0xde, 0x6f, 0x31, 0xf3, 0xfd, 0xde, 0x04, 0xfc, 0xf3,
0x68, 0x51, 0xf1, 0x7f, 0x16, 0x87, 0xb8, 0x78, 0x58, 0x44, 0x9f, 0x7a, 0x9a, 0x2d, 0xf7, 0xc7, 0xe2, 0x71, 0xe9, 0x70, 0x46, 0xb4, 0xa8, 0xf8, 0x3f, 0x8b, 0x43, 0x5c, 0x3c, 0x2e, 0xa1, 0x4f,
0xe4, 0xe2, 0xee, 0xb5, 0xfc, 0x53, 0x2c, 0xac, 0xd9, 0x92, 0x85, 0xa5, 0xa2, 0x58, 0xca, 0x37, 0x3d, 0x7d, 0x96, 0x07, 0x13, 0x72, 0x71, 0xb7, 0x59, 0xfe, 0x29, 0x16, 0xd6, 0x67, 0xc9, 0xc1,
0x4a, 0xd2, 0x6e, 0xa9, 0x52, 0x6a, 0x94, 0x24, 0xda, 0x0c, 0xca, 0x70, 0x68, 0x0d, 0xb2, 0x87, 0x4a, 0x49, 0x2c, 0x17, 0x9a, 0x65, 0x69, 0xbf, 0x5c, 0x2d, 0x37, 0xcb, 0x12, 0xed, 0x03, 0x65,
0x47, 0x85, 0x4a, 0xb9, 0xbe, 0x2f, 0x1d, 0x55, 0xed, 0x5f, 0x6c, 0x34, 0x86, 0x32, 0x30, 0x57, 0x38, 0xb4, 0x01, 0xb9, 0xe3, 0x93, 0x62, 0xb5, 0xd2, 0x38, 0x94, 0x4e, 0x6a, 0xf6, 0x2f, 0x36,
0x29, 0xd7, 0x1b, 0x0c, 0x50, 0xcf, 0xc4, 0x2d, 0xc8, 0x5e, 0xa9, 0x21, 0x15, 0xf3, 0x87, 0xf9, 0x1a, 0x43, 0x19, 0x58, 0xa8, 0x56, 0x1a, 0x4d, 0x06, 0x68, 0x64, 0xe2, 0x16, 0xe4, 0xa0, 0xdc,
0x62, 0xb9, 0xf1, 0x3a, 0x93, 0x40, 0x3c, 0xac, 0x78, 0x79, 0xd7, 0xab, 0xf9, 0xc3, 0xfa, 0x7e, 0x94, 0x4a, 0x85, 0xe3, 0x42, 0xa9, 0xd2, 0x7c, 0x91, 0x49, 0x20, 0x1e, 0xd6, 0xbc, 0xbc, 0x1b,
0xad, 0x91, 0x49, 0x22, 0x04, 0x0b, 0x84, 0xde, 0x06, 0xd5, 0x33, 0x29, 0x8b, 0x43, 0xb1, 0x52, 0xb5, 0xc2, 0x71, 0xe3, 0xb0, 0xde, 0xcc, 0x24, 0x11, 0x82, 0x25, 0x42, 0x6f, 0x83, 0x1a, 0x99,
0xab, 0x3a, 0x32, 0x4c, 0xa3, 0x25, 0xc8, 0xd8, 0x33, 0x8b, 0xa5, 0xfc, 0x2e, 0xa9, 0xea, 0xcd, 0x94, 0xc5, 0xa1, 0x54, 0xad, 0xd7, 0x1c, 0x19, 0x66, 0xd1, 0x0a, 0x64, 0xec, 0x99, 0xc5, 0x72,
0xa0, 0xab, 0x30, 0x5f, 0xfa, 0xc9, 0x61, 0xbe, 0xba, 0x6b, 0x23, 0xce, 0xa2, 0x4d, 0x58, 0x73, 0x61, 0x9f, 0x14, 0xf4, 0xe6, 0xd0, 0x32, 0x2c, 0x96, 0x7f, 0x72, 0x5c, 0xa8, 0xed, 0xdb, 0x88,
0x8b, 0x23, 0x31, 0xaa, 0xd2, 0x2e, 0xa9, 0xcc, 0xd5, 0x33, 0x80, 0xae, 0x43, 0x86, 0xf5, 0xb9, 0xf3, 0x68, 0x1b, 0x36, 0xdc, 0xe2, 0x48, 0x8c, 0xaa, 0xbc, 0x4f, 0x8a, 0x72, 0x8d, 0x0c, 0xa0,
0x8a, 0xb5, 0xea, 0x6e, 0xb9, 0x51, 0xae, 0x55, 0x33, 0x69, 0x5a, 0xc6, 0x5b, 0x04, 0xb0, 0x24, 0x5b, 0x90, 0x61, 0x2d, 0xae, 0x52, 0xbd, 0xb6, 0x5f, 0x69, 0x56, 0xea, 0xb5, 0x4c, 0x9a, 0x56,
0x67, 0xcc, 0xe6, 0x46, 0xd7, 0xf6, 0xe6, 0x69, 0x6d, 0xcf, 0xae, 0x5d, 0xff, 0x26, 0x06, 0xcb, 0xf0, 0xb2, 0x00, 0x96, 0xe4, 0x8c, 0xd9, 0xc2, 0xf8, 0xb2, 0xde, 0x22, 0x2d, 0xeb, 0xd9, 0x65,
0xb4, 0x78, 0x6d, 0x97, 0xca, 0x6d, 0x87, 0xb5, 0x05, 0x19, 0x5a, 0xf4, 0x92, 0xfc, 0x57, 0xc1, 0xeb, 0xdf, 0xc4, 0x60, 0x95, 0xd6, 0xad, 0xed, 0x2a, 0xb9, 0xed, 0xab, 0x76, 0x20, 0x43, 0xeb,
0x02, 0x85, 0xbf, 0xb4, 0x93, 0x0f, 0xbb, 0xd1, 0x14, 0x73, 0x35, 0x9a, 0xca, 0xfe, 0x54, 0xec, 0x5d, 0x92, 0xff, 0x16, 0x58, 0xa2, 0xf0, 0x67, 0x76, 0xde, 0x61, 0xf7, 0x98, 0x62, 0xae, 0x1e,
0x9e, 0xb7, 0x25, 0xe3, 0x9b, 0x6d, 0x58, 0x76, 0x7f, 0x10, 0x92, 0x2b, 0x3c, 0x18, 0xce, 0x6d, 0x53, 0xc5, 0x9f, 0x85, 0xdd, 0xf7, 0x76, 0x63, 0x7c, 0xb3, 0x8d, 0x4a, 0xec, 0x8f, 0x42, 0xd2,
0x58, 0x1c, 0x75, 0x91, 0x54, 0xfe, 0x82, 0xae, 0xee, 0x39, 0xac, 0xf8, 0xe5, 0x65, 0x06, 0x7d, 0x84, 0x87, 0xa3, 0xb9, 0x8d, 0x0a, 0xa1, 0xae, 0x92, 0xc5, 0x5f, 0xd1, 0xcb, 0x3d, 0x81, 0x35,
0x3f, 0xd0, 0x38, 0x71, 0x7c, 0xaf, 0x83, 0xeb, 0x60, 0x08, 0xff, 0xc2, 0xc1, 0x8c, 0x0d, 0xb6, 0xbf, 0xbc, 0xcc, 0xa0, 0x1f, 0x04, 0x7a, 0x26, 0x8e, 0xdb, 0x75, 0x70, 0x1d, 0x0c, 0xe1, 0x5f,
0x62, 0x1c, 0xcb, 0x2f, 0x79, 0xca, 0xa5, 0xb3, 0x16, 0xc4, 0xa9, 0xbe, 0xba, 0x5b, 0x1e, 0x31, 0x38, 0x98, 0xb3, 0xc1, 0x56, 0x78, 0x63, 0xf9, 0x25, 0x4f, 0xa5, 0x74, 0xde, 0x82, 0x38, 0x85,
0x7f, 0xcb, 0x23, 0xf4, 0x9c, 0xe3, 0xa1, 0xe7, 0xfc, 0x23, 0x98, 0x6f, 0x5a, 0xe2, 0x2b, 0x9a, 0x57, 0x77, 0xb7, 0x23, 0xe6, 0xef, 0x76, 0x84, 0x9e, 0x73, 0x3c, 0xf4, 0x9c, 0x7f, 0x04, 0x8b,
0x2a, 0x99, 0x4a, 0xd7, 0xae, 0x86, 0x06, 0x5b, 0x94, 0x0d, 0xfb, 0x5d, 0x81, 0x38, 0x67, 0x13, 0x2d, 0x4b, 0x7c, 0x45, 0x53, 0x25, 0x53, 0xe9, 0xd9, 0x85, 0xd0, 0x60, 0x77, 0xb2, 0x69, 0x3f,
0x58, 0x20, 0xb4, 0x09, 0x73, 0xa4, 0x65, 0x29, 0x99, 0x9a, 0xd4, 0x37, 0x70, 0x36, 0x49, 0x6a, 0x29, 0x10, 0x17, 0x6c, 0x02, 0x0b, 0x84, 0xb6, 0x61, 0x81, 0x74, 0x2b, 0x25, 0x53, 0x93, 0x06,
0x43, 0x40, 0x60, 0x0d, 0xed, 0xc8, 0xc0, 0xc2, 0xdf, 0x71, 0xb0, 0x4c, 0x4b, 0x5e, 0x7e, 0x75, 0x06, 0xce, 0x25, 0x49, 0x59, 0x08, 0x08, 0xac, 0xa9, 0x9d, 0x18, 0x58, 0xf8, 0x3b, 0x0e, 0x56,
0x1c, 0xd5, 0xba, 0x71, 0x6b, 0x9c, 0xef, 0x4a, 0x0c, 0x65, 0xf8, 0xbe, 0x32, 0xfe, 0x2c, 0xac, 0x69, 0xb5, 0xcb, 0xaf, 0x8e, 0xe3, 0xba, 0x36, 0x6e, 0x8d, 0xf3, 0xdd, 0x86, 0xa1, 0x0c, 0xdf,
0xf8, 0xe7, 0x63, 0x69, 0xfe, 0x2f, 0x63, 0xb0, 0x64, 0xc5, 0x67, 0xf6, 0xc0, 0x65, 0x87, 0xd0, 0x54, 0xb2, 0x9f, 0x83, 0x35, 0xff, 0x7c, 0x2c, 0xc3, 0xff, 0x65, 0x0c, 0x56, 0xac, 0xd0, 0xcc,
0x13, 0x9c, 0xa4, 0x6f, 0x33, 0x13, 0x81, 0xcd, 0xdc, 0xf7, 0x27, 0xd1, 0x77, 0xdd, 0x11, 0xa6, 0x1e, 0xb8, 0xee, 0xe8, 0x79, 0x8a, 0x93, 0xf4, 0x6d, 0x66, 0x22, 0xb0, 0x99, 0x87, 0xfe, 0xfc,
0x7f, 0x05, 0xef, 0x6b, 0x2f, 0xff, 0x92, 0x83, 0x65, 0xdf, 0x7c, 0xcc, 0x5e, 0x3e, 0xf1, 0x67, 0xf9, 0x1d, 0x77, 0x70, 0xe9, 0x5f, 0xc1, 0x9b, 0xda, 0xcb, 0xbf, 0xe4, 0x60, 0xd5, 0x37, 0x1f,
0x05, 0xb7, 0x22, 0xe4, 0x7b, 0xa7, 0xbc, 0xe0, 0xb1, 0x1d, 0x8f, 0x4f, 0x66, 0x96, 0xff, 0x1c, 0xb3, 0x97, 0x4f, 0xfc, 0x09, 0xc1, 0xdd, 0x08, 0xf9, 0x5e, 0x2b, 0x25, 0xf8, 0xc0, 0x0e, 0xc5,
0x83, 0xf5, 0xc1, 0xa5, 0x46, 0x1e, 0x0d, 0xb4, 0x26, 0x28, 0x6b, 0x5d, 0xac, 0x37, 0xff, 0x99, 0xa7, 0x33, 0xcb, 0x7f, 0x8e, 0xc1, 0xe6, 0xf0, 0x52, 0x23, 0xef, 0x05, 0xda, 0x53, 0x54, 0xb4,
0xdf, 0xe1, 0x6e, 0x07, 0xef, 0xd9, 0x10, 0x91, 0x86, 0x39, 0xde, 0xd0, 0x6a, 0x70, 0x62, 0xd2, 0xae, 0xd6, 0x96, 0xff, 0xcc, 0xef, 0x70, 0x77, 0x83, 0xf7, 0x6c, 0x88, 0x48, 0xa3, 0x1c, 0x6f,
0x6a, 0xf0, 0x85, 0x34, 0xe0, 0xf7, 0xdc, 0x85, 0x6e, 0xaf, 0xf8, 0x4c, 0x13, 0xc6, 0xec, 0x18, 0x68, 0x21, 0x38, 0x31, 0x6d, 0x21, 0xf8, 0x4a, 0x1a, 0xf0, 0x7b, 0xee, 0x1a, 0xb7, 0x57, 0x7c,
0x3d, 0x81, 0x6b, 0x24, 0x05, 0x70, 0xde, 0xbc, 0xd8, 0x9d, 0x78, 0xea, 0x12, 0x67, 0xc4, 0x65, 0xa6, 0x09, 0x13, 0x36, 0x8b, 0x3e, 0x84, 0x9b, 0x24, 0xfa, 0x77, 0x9e, 0xbb, 0xd8, 0x4d, 0x78,
0x6b, 0xd8, 0x79, 0xe8, 0xc1, 0xba, 0x24, 0x2d, 0xe1, 0xdb, 0x04, 0xac, 0x58, 0x29, 0x42, 0xdd, 0xea, 0x12, 0xe7, 0xc4, 0x55, 0x6b, 0xd8, 0x79, 0xe3, 0xc1, 0x1a, 0x24, 0x6d, 0xe1, 0xdb, 0x04,
0x94, 0xdb, 0x93, 0xf4, 0x0f, 0x7e, 0x3b, 0x58, 0x8e, 0x8d, 0x79, 0x8f, 0x25, 0x9c, 0xeb, 0x38, 0xac, 0x59, 0xd9, 0x41, 0xc3, 0x94, 0x3b, 0xd3, 0xb4, 0x0e, 0x7e, 0x3b, 0x58, 0x89, 0x8d, 0x79,
0x55, 0x58, 0x94, 0x83, 0x45, 0xc3, 0x94, 0xdb, 0xc4, 0x1d, 0xc8, 0x7a, 0x1b, 0x9b, 0x52, 0x4f, 0x8f, 0x25, 0x9c, 0xeb, 0x24, 0x05, 0x58, 0x94, 0x87, 0xac, 0x61, 0xca, 0x1d, 0xe2, 0x0e, 0x64,
0x36, 0xdf, 0x32, 0x5b, 0xbf, 0xca, 0x86, 0x1a, 0x64, 0xe4, 0x50, 0x36, 0xdf, 0x5e, 0xd2, 0x41, 0xbd, 0x83, 0x4d, 0xa9, 0x2f, 0x9b, 0xaf, 0x98, 0xad, 0x2f, 0xb3, 0xa1, 0x26, 0x19, 0x39, 0x96,
0xa2, 0x1f, 0xfb, 0x9d, 0xc2, 0x87, 0x23, 0xd6, 0x32, 0x44, 0xb7, 0x7e, 0x12, 0x51, 0xb2, 0x7f, 0xcd, 0x57, 0xd7, 0x74, 0x90, 0xe8, 0xc7, 0x7e, 0xa7, 0xf0, 0xee, 0x98, 0xb5, 0x8c, 0xd0, 0xad,
0x34, 0x82, 0xe5, 0xe8, 0x52, 0xfd, 0xc5, 0x4b, 0xd4, 0xdf, 0x71, 0xb5, 0xff, 0x3a, 0x5c, 0x0b, 0x9f, 0x44, 0x54, 0xeb, 0xdf, 0x1b, 0xc3, 0x72, 0x7c, 0x95, 0xfe, 0xea, 0xd5, 0xe9, 0xef, 0xb8,
0x2c, 0x9e, 0x5d, 0x21, 0x6d, 0xc8, 0x5a, 0x43, 0x47, 0xaa, 0x31, 0xa1, 0x3a, 0x46, 0x68, 0x4c, 0xd0, 0x7f, 0x0b, 0x6e, 0x06, 0x16, 0xcf, 0xae, 0x90, 0x0e, 0xe4, 0xac, 0xa1, 0x13, 0xd5, 0x98,
0x2c, 0x42, 0x63, 0x84, 0x55, 0xb8, 0x1e, 0x32, 0x11, 0x93, 0xe2, 0x6f, 0x92, 0x54, 0x8c, 0xc9, 0x52, 0x1d, 0x23, 0x34, 0x26, 0x16, 0xa1, 0x31, 0xc2, 0x3a, 0xdc, 0x0a, 0x99, 0x88, 0x49, 0xf1,
0x1b, 0x4f, 0x9f, 0x47, 0x59, 0xc5, 0x47, 0xee, 0x63, 0x0f, 0xed, 0xd1, 0xbc, 0x0f, 0xbb, 0xd8, 0x37, 0x49, 0x2a, 0xc6, 0xf4, 0x3d, 0xa7, 0xcf, 0xa3, 0xac, 0xe2, 0x7d, 0xf7, 0xb1, 0x87, 0xb6,
0x80, 0xb4, 0x1b, 0x8f, 0x5d, 0x83, 0xe6, 0x08, 0xc3, 0x49, 0x5e, 0xa8, 0x1f, 0x96, 0xf2, 0xf5, 0x67, 0xde, 0x84, 0x5d, 0x6c, 0x41, 0xda, 0x8d, 0xc7, 0xae, 0x41, 0x73, 0x8c, 0xe1, 0x24, 0xaf,
0xc3, 0x2a, 0x03, 0xa3, 0x9a, 0xf6, 0x86, 0xb6, 0x91, 0x5b, 0x31, 0xc4, 0xac, 0xde, 0x04, 0xcc, 0xd4, 0x0a, 0x4b, 0xf9, 0x5a, 0x61, 0xd5, 0xa1, 0x51, 0xcd, 0x7a, 0x43, 0xdb, 0xc8, 0xad, 0x18,
0x6a, 0xc6, 0xdb, 0x64, 0x8b, 0x64, 0xfa, 0xff, 0xc0, 0xb0, 0x98, 0x52, 0x87, 0x76, 0xbf, 0x84, 0x61, 0x56, 0x2f, 0x03, 0x66, 0x35, 0xe7, 0xed, 0xaf, 0x45, 0x32, 0xfd, 0x7f, 0x60, 0x58, 0x4c,
0x37, 0xc0, 0x53, 0x8d, 0x9f, 0xbc, 0x1f, 0xe5, 0x53, 0xa3, 0x98, 0x5f, 0x8d, 0x84, 0x75, 0x58, 0xa9, 0x43, 0x1b, 0x5f, 0xc2, 0x4b, 0xe0, 0xa9, 0xc6, 0x4f, 0xdf, 0x8a, 0xf2, 0xa9, 0x51, 0xcc,
0x0d, 0xe5, 0xcd, 0xa6, 0xfe, 0x63, 0x8e, 0x0a, 0xe6, 0x14, 0xba, 0xea, 0xa6, 0x6c, 0x1a, 0xe3, 0xaf, 0x46, 0xc2, 0x26, 0xac, 0x87, 0xf2, 0x66, 0x53, 0xff, 0x31, 0x47, 0x05, 0x73, 0x6a, 0x5c,
0x4e, 0xcd, 0x06, 0xdd, 0x53, 0x53, 0x10, 0xd1, 0xe0, 0x09, 0x4d, 0x42, 0xf8, 0x53, 0x8e, 0xee, 0x0d, 0x53, 0x36, 0x8d, 0x49, 0xa7, 0x66, 0x83, 0xee, 0xa9, 0x29, 0x88, 0x68, 0xf0, 0x94, 0x26,
0x83, 0x5f, 0x16, 0x76, 0xdb, 0xde, 0x85, 0x64, 0x9f, 0xd4, 0xf2, 0x69, 0xd4, 0xb5, 0xe8, 0x35, 0x21, 0xfc, 0x29, 0x47, 0xf7, 0xc1, 0x2f, 0x0b, 0xbb, 0x6d, 0xdf, 0x81, 0xe4, 0x80, 0x94, 0xf1,
0x82, 0x23, 0x6b, 0x48, 0xa4, 0x18, 0x97, 0x56, 0x1d, 0x15, 0x7e, 0xc9, 0x41, 0xda, 0xc5, 0x1f, 0x69, 0xd4, 0x95, 0xf5, 0x1a, 0xc1, 0x89, 0x35, 0x24, 0x52, 0x8c, 0x6b, 0x2b, 0x8c, 0x0a, 0xbf,
0xad, 0xc1, 0xac, 0x53, 0xfe, 0xb1, 0xf3, 0x1d, 0x07, 0x60, 0x1d, 0xbf, 0xa9, 0x99, 0x72, 0x87, 0xe4, 0x20, 0xed, 0xe2, 0x8f, 0x36, 0x60, 0xde, 0xa9, 0xfc, 0xd8, 0xf9, 0x8e, 0x03, 0xb0, 0x8e,
0xbd, 0x33, 0xa1, 0x1f, 0x56, 0x8a, 0xda, 0x37, 0x30, 0x0d, 0x87, 0xe3, 0x22, 0xf9, 0x8d, 0xee, 0xdf, 0xd4, 0x4c, 0xb9, 0xcb, 0x9e, 0x98, 0xd0, 0x0f, 0x2b, 0x45, 0x1d, 0x18, 0x98, 0x86, 0xc3,
0x43, 0xa2, 0xaf, 0x2a, 0x26, 0x31, 0xfb, 0x05, 0xbf, 0x3d, 0x93, 0xa9, 0x72, 0x47, 0xaa, 0x62, 0x71, 0x91, 0xfc, 0x46, 0x0f, 0x20, 0x31, 0x50, 0x15, 0x93, 0x98, 0xfd, 0x92, 0xdf, 0x9e, 0xc9,
0x8a, 0x04, 0x4b, 0xb8, 0x07, 0x09, 0xeb, 0xcb, 0x5b, 0x81, 0x98, 0x85, 0x64, 0xe1, 0x75, 0xa3, 0x54, 0xf9, 0x13, 0x55, 0x31, 0x45, 0x82, 0x25, 0xdc, 0x87, 0x84, 0xf5, 0xe5, 0xad, 0x40, 0xcc,
0x54, 0xcf, 0x70, 0x08, 0x20, 0x55, 0xa6, 0xf9, 0x7a, 0x4c, 0xa8, 0xd8, 0x0f, 0x4e, 0x9d, 0x45, 0x43, 0xb2, 0xf8, 0xa2, 0x59, 0x6e, 0x64, 0x38, 0x04, 0x90, 0xaa, 0xd0, 0x7c, 0x3d, 0x26, 0x54,
0x58, 0x2e, 0x40, 0x3e, 0x56, 0x35, 0xbd, 0x2b, 0x77, 0x88, 0xcc, 0x33, 0xa2, 0xf3, 0x1d, 0xdd, 0xed, 0xb7, 0xa6, 0xce, 0x22, 0x2c, 0x17, 0x20, 0x9f, 0xaa, 0x9a, 0xde, 0x93, 0xbb, 0x44, 0xe6,
0x22, 0xa1, 0x05, 0xc5, 0x35, 0xe7, 0x44, 0xc2, 0xea, 0x45, 0x5f, 0x50, 0xdd, 0x8a, 0xaa, 0x14, 0x39, 0xd1, 0xf9, 0x8e, 0xee, 0x8e, 0xd0, 0x5a, 0xe2, 0x86, 0x73, 0x22, 0x61, 0xf5, 0xa2, 0x2f,
0xe5, 0x43, 0x2b, 0x45, 0xeb, 0x9e, 0x5b, 0x76, 0x44, 0x8d, 0xe8, 0x57, 0x31, 0x58, 0x0e, 0xc5, 0xa8, 0x6e, 0x45, 0x55, 0x8a, 0x0a, 0xa1, 0x95, 0xa2, 0x4d, 0xcf, 0x2d, 0x3b, 0xa6, 0x46, 0xf4,
0x43, 0x8f, 0xdd, 0xd5, 0xa1, 0x9b, 0x43, 0x79, 0xba, 0xeb, 0x42, 0xff, 0xcd, 0xd1, 0xba, 0xd0, 0xab, 0x18, 0xac, 0x86, 0xe2, 0xa1, 0x0f, 0xdc, 0xd5, 0xa1, 0x3b, 0x23, 0x79, 0xba, 0xeb, 0x42,
0x8e, 0xa7, 0x2e, 0x74, 0x67, 0x24, 0xbd, 0xbb, 0x22, 0xf4, 0x57, 0x5c, 0x44, 0x45, 0xa8, 0xde, 0xff, 0xcd, 0xd1, 0xba, 0xd0, 0x9e, 0xa7, 0x2e, 0xf4, 0xf6, 0x58, 0x7a, 0x77, 0x45, 0xe8, 0xaf,
0xc8, 0xef, 0x95, 0xa4, 0xa3, 0x2a, 0xfd, 0xeb, 0x54, 0x84, 0x96, 0x20, 0x33, 0xa8, 0x93, 0x48, 0xb8, 0x88, 0x8a, 0x50, 0xa3, 0x59, 0x38, 0x28, 0x4b, 0x27, 0x35, 0xfa, 0xd7, 0xa9, 0x08, 0xad,
0xf5, 0x46, 0xbe, 0x51, 0xcf, 0xc4, 0x82, 0xd5, 0x98, 0x78, 0x68, 0xad, 0x25, 0x31, 0xba, 0xac, 0x40, 0x66, 0x58, 0x27, 0x91, 0x1a, 0xcd, 0x42, 0xb3, 0x91, 0x89, 0x05, 0xab, 0x31, 0xf1, 0xd0,
0x92, 0xa4, 0x28, 0xab, 0x80, 0x18, 0xf5, 0x41, 0xed, 0xa8, 0xda, 0x90, 0xf6, 0xc4, 0xda, 0xd1, 0x5a, 0x4b, 0x62, 0x7c, 0x59, 0x25, 0x49, 0x51, 0xd6, 0x01, 0x31, 0xea, 0xa3, 0xfa, 0x49, 0xad,
0x21, 0x7b, 0x72, 0xe5, 0xd4, 0x5c, 0x96, 0x00, 0xb1, 0x23, 0x73, 0x3f, 0xa2, 0xff, 0x73, 0x0e, 0x29, 0x1d, 0x88, 0xf5, 0x93, 0x63, 0xf6, 0xda, 0xca, 0xa9, 0xb9, 0xac, 0x00, 0x62, 0x47, 0xe6,
0x16, 0x3d, 0x60, 0x76, 0x82, 0xae, 0x6e, 0x37, 0xe7, 0xe9, 0x76, 0x3f, 0x84, 0x25, 0x2b, 0x6d, 0x7e, 0x3f, 0xff, 0xe7, 0x1c, 0x64, 0x3d, 0x60, 0x76, 0x82, 0xae, 0x46, 0x37, 0xe7, 0x69, 0x74,
0xa4, 0xe6, 0x62, 0x48, 0x3d, 0xac, 0x93, 0x2a, 0x37, 0x53, 0xfc, 0xab, 0x5d, 0xf9, 0x8c, 0x75, 0x3f, 0x82, 0x15, 0x2b, 0x6d, 0xa4, 0xe6, 0x62, 0x48, 0x7d, 0xac, 0x93, 0x02, 0x37, 0x53, 0xfc,
0x02, 0x0e, 0xb1, 0x6e, 0x31, 0xbe, 0x84, 0x5a, 0xaf, 0xf0, 0x4d, 0x9c, 0x06, 0x27, 0x13, 0x27, 0xe5, 0x9e, 0x7c, 0xc1, 0x9a, 0x00, 0xc7, 0x58, 0xb7, 0x18, 0x5f, 0x43, 0x99, 0x57, 0xf8, 0x26,
0x37, 0x23, 0x1d, 0x55, 0x30, 0xfb, 0x89, 0x4f, 0x90, 0xfd, 0x44, 0xb8, 0xb9, 0xc4, 0x44, 0x11, 0x4e, 0x83, 0x93, 0xa9, 0x93, 0x9b, 0xb1, 0x8e, 0x2a, 0x98, 0xfd, 0xc4, 0xa7, 0xc8, 0x7e, 0x22,
0xf1, 0xe4, 0x17, 0x7b, 0x75, 0x70, 0x79, 0xd3, 0xf0, 0xf5, 0xbe, 0x5b, 0x89, 0x47, 0xa6, 0x5b, 0xdc, 0x5c, 0x62, 0xaa, 0x88, 0x78, 0xfa, 0x8b, 0xbd, 0x36, 0xbc, 0xbc, 0x69, 0xf8, 0xfa, 0xc0,
0xa9, 0x6f, 0x0a, 0xdc, 0xcf, 0x2e, 0x2b, 0x59, 0xce, 0xd3, 0xa0, 0xec, 0x02, 0x49, 0xd2, 0xf6, 0xad, 0xc4, 0x63, 0xd3, 0xad, 0xd4, 0x37, 0x45, 0xee, 0x67, 0xd7, 0x95, 0x2c, 0x17, 0x68, 0x50,
0xff, 0x70, 0x30, 0x53, 0x6e, 0x61, 0xd5, 0xa4, 0x6b, 0x9b, 0xf7, 0xfc, 0x9f, 0x05, 0x5a, 0x8b, 0x76, 0x85, 0x24, 0x69, 0xf7, 0x7f, 0x38, 0x98, 0xab, 0xb4, 0xb1, 0x6a, 0xd2, 0xb5, 0x2d, 0x7a,
0xf8, 0xf7, 0x0b, 0xb2, 0x30, 0x7e, 0x7d, 0xe8, 0x3f, 0x67, 0x08, 0x53, 0xe8, 0xc4, 0xf5, 0x3f, 0xfe, 0xc5, 0x02, 0x6d, 0x44, 0xfc, 0xe7, 0x05, 0x59, 0x18, 0xbf, 0x39, 0xf2, 0xff, 0x32, 0x84,
0x22, 0x9e, 0x76, 0xc6, 0x07, 0x01, 0xca, 0x10, 0x3f, 0xc7, 0xdf, 0x1e, 0x81, 0xe5, 0xcc, 0xf3, 0x19, 0x74, 0xe6, 0xfa, 0xf7, 0x10, 0x4f, 0x27, 0xe3, 0xad, 0x00, 0x65, 0x88, 0x9f, 0xe3, 0xef,
0x04, 0x92, 0xe4, 0x45, 0x3d, 0x5a, 0x72, 0x5e, 0xf5, 0xbb, 0x1e, 0xdc, 0xf3, 0xcb, 0x3e, 0xa8, 0x8d, 0xc1, 0x72, 0xe6, 0xf9, 0x10, 0x92, 0xe4, 0x31, 0x3d, 0x5a, 0x71, 0x1e, 0xf4, 0xbb, 0xde,
0x4d, 0xb7, 0xfd, 0x8f, 0xb3, 0x00, 0x83, 0x5c, 0x13, 0xbd, 0x80, 0x39, 0xf7, 0xa3, 0x5e, 0xb4, 0xda, 0xf3, 0xab, 0x3e, 0xa8, 0x4d, 0xb7, 0xfb, 0x8f, 0xf3, 0x00, 0xc3, 0x5c, 0x13, 0x3d, 0x85,
0x3a, 0xe4, 0x49, 0x39, 0xbf, 0x16, 0x3e, 0xe8, 0xc8, 0xf4, 0x02, 0xe6, 0xdc, 0x0f, 0xb9, 0x06, 0x05, 0xf7, 0x7b, 0x5e, 0xb4, 0x3e, 0xe2, 0x35, 0x39, 0xbf, 0x11, 0x3e, 0xe8, 0xc8, 0xf4, 0x14,
0xcc, 0x42, 0x1e, 0x93, 0x0d, 0x98, 0x85, 0xbe, 0xfd, 0x9a, 0x42, 0x1d, 0xb8, 0x16, 0xf1, 0x94, 0x16, 0xdc, 0x6f, 0xb8, 0x86, 0xcc, 0x42, 0xde, 0x91, 0x0d, 0x99, 0x85, 0x3e, 0xfb, 0x9a, 0x41,
0x07, 0xdd, 0x19, 0xef, 0xc1, 0x13, 0xff, 0xbd, 0x31, 0xdf, 0x04, 0x09, 0x53, 0x48, 0x87, 0xeb, 0x5d, 0xb8, 0x19, 0xf1, 0x8a, 0x07, 0xbd, 0x3d, 0xd9, 0x5b, 0x27, 0xfe, 0x7b, 0x13, 0x3e, 0x07,
0x91, 0x2f, 0x58, 0xd0, 0xd6, 0xb8, 0xef, 0x6b, 0xf8, 0xbb, 0x63, 0x60, 0x3a, 0x73, 0xf6, 0x81, 0x12, 0x66, 0x90, 0x0e, 0xb7, 0x22, 0x1f, 0xaf, 0xa0, 0x9d, 0x49, 0x9f, 0xd6, 0xf0, 0xef, 0x4c,
0x8f, 0x6e, 0x9b, 0xa3, 0xbb, 0x63, 0xbf, 0xe7, 0xe0, 0xef, 0x8d, 0xdf, 0x85, 0x17, 0xa6, 0xd0, 0x80, 0xe9, 0xcc, 0x39, 0x00, 0x3e, 0xba, 0x63, 0x8e, 0xde, 0x99, 0xf8, 0x29, 0x07, 0x7f, 0x7f,
0x3e, 0xa4, 0x5d, 0xfd, 0x53, 0xc4, 0x87, 0x36, 0x55, 0x29, 0xe3, 0xd5, 0x21, 0x0d, 0x57, 0xca, 0xf2, 0x06, 0xbc, 0x30, 0x83, 0x0e, 0x21, 0xed, 0x6a, 0x9d, 0x22, 0x3e, 0xb4, 0x9f, 0x4a, 0x19,
0xc9, 0xd5, 0xd2, 0x1a, 0x70, 0x0a, 0x36, 0xe7, 0x06, 0x9c, 0x42, 0x7a, 0x60, 0xfe, 0xed, 0xf7, 0xaf, 0x8f, 0xe8, 0xb5, 0x52, 0x4e, 0xae, 0x6e, 0xd6, 0x90, 0x53, 0xb0, 0x2f, 0x37, 0xe4, 0x14,
0x5d, 0xf2, 0x61, 0xdb, 0x1f, 0x1e, 0x25, 0x84, 0x6d, 0x7f, 0x44, 0xc4, 0x20, 0x4c, 0xa1, 0xcf, 0xd2, 0xfe, 0xf2, 0x6f, 0xbf, 0xef, 0x92, 0x0f, 0xdb, 0xfe, 0xf0, 0x28, 0x21, 0x6c, 0xfb, 0x23,
0x60, 0xc1, 0x5b, 0xa6, 0x46, 0xeb, 0x43, 0xcb, 0xed, 0xfc, 0x8d, 0xa8, 0x61, 0x37, 0x4b, 0x6f, 0x22, 0x06, 0x61, 0x06, 0x7d, 0x06, 0x4b, 0xde, 0x32, 0x35, 0xda, 0x1c, 0x59, 0x6e, 0xe7, 0x6f,
0x55, 0x74, 0xc0, 0x32, 0xb4, 0x3a, 0x3b, 0x60, 0x19, 0x51, 0x4c, 0x9d, 0xb2, 0xfc, 0x93, 0xa7, 0x47, 0x0d, 0xbb, 0x59, 0x7a, 0xab, 0xa2, 0x43, 0x96, 0xa1, 0xd5, 0xd9, 0x21, 0xcb, 0x88, 0x62,
0xd6, 0x37, 0xf0, 0x4f, 0x61, 0x25, 0xca, 0x81, 0x7f, 0x0a, 0x2d, 0x10, 0x0a, 0x53, 0x48, 0x81, 0xea, 0x8c, 0xe5, 0x9f, 0x3c, 0xb5, 0xbe, 0xa1, 0x7f, 0x0a, 0x2b, 0x51, 0x0e, 0xfd, 0x53, 0x68,
0x95, 0xf0, 0x52, 0x13, 0xba, 0x3d, 0x56, 0x25, 0x8d, 0xbf, 0x33, 0x0a, 0xcd, 0x99, 0xaa, 0x09, 0x81, 0x50, 0x98, 0x41, 0x0a, 0xac, 0x85, 0x97, 0x9a, 0xd0, 0xbd, 0x89, 0x2a, 0x69, 0xfc, 0xdb,
0x8b, 0x21, 0xed, 0x6d, 0x24, 0x0c, 0xed, 0x7d, 0xd3, 0x49, 0x6e, 0x8d, 0xd1, 0x1f, 0x17, 0xac, 0xe3, 0xd0, 0x9c, 0xa9, 0x5a, 0x90, 0x0d, 0xe9, 0x6c, 0x23, 0x61, 0x64, 0xdb, 0x9b, 0x4e, 0x72,
0x68, 0x63, 0xfb, 0xdf, 0x92, 0x90, 0x20, 0xd7, 0x7e, 0x03, 0xae, 0xf8, 0xea, 0x09, 0xe8, 0xc6, 0x77, 0x82, 0xd6, 0xb8, 0x60, 0x45, 0x1b, 0xbb, 0xff, 0x96, 0x84, 0x04, 0xb9, 0xf6, 0x9b, 0x70,
0xf0, 0x2a, 0x0b, 0xbf, 0x11, 0x39, 0xee, 0xac, 0xe1, 0x0d, 0x5c, 0x0d, 0x54, 0x08, 0xd0, 0xa6, 0xc3, 0x57, 0x4f, 0x40, 0xb7, 0x47, 0x57, 0x59, 0xf8, 0xad, 0xc8, 0x71, 0x67, 0x0d, 0x2f, 0x61,
0x9b, 0x2e, 0xac, 0x4a, 0xc1, 0xdf, 0x1c, 0x82, 0xe1, 0xe7, 0xed, 0xf5, 0x6d, 0x9b, 0xa3, 0x52, 0x39, 0x50, 0x21, 0x40, 0xdb, 0x6e, 0xba, 0xb0, 0x2a, 0x05, 0x7f, 0x67, 0x04, 0x86, 0x9f, 0xb7,
0x58, 0x2f, 0xef, 0x28, 0x7f, 0xf6, 0x05, 0x8d, 0xb2, 0xfc, 0x9e, 0x4c, 0xf0, 0xca, 0x15, 0xea, 0xd7, 0xb7, 0x6d, 0x8f, 0x4b, 0x61, 0xbd, 0xbc, 0xa3, 0xfc, 0xd9, 0x17, 0x34, 0xca, 0xf2, 0x7b,
0xc3, 0x6e, 0x0d, 0xc5, 0x71, 0x66, 0xf8, 0xdc, 0x09, 0xef, 0x5c, 0x19, 0x14, 0xf2, 0x08, 0x17, 0x32, 0xc1, 0x2b, 0x57, 0xa8, 0x0f, 0xbb, 0x3b, 0x12, 0xc7, 0x99, 0xe1, 0x73, 0x27, 0xbc, 0x73,
0x9a, 0xe9, 0xf1, 0xc2, 0x30, 0x14, 0x87, 0xfd, 0x2b, 0xc8, 0xf8, 0xef, 0x79, 0xb4, 0x31, 0x22, 0x65, 0x50, 0xc8, 0x23, 0x5c, 0x68, 0xa6, 0xc7, 0x0b, 0xa3, 0x50, 0x1c, 0xf6, 0xcf, 0x21, 0xe3,
0xec, 0xe0, 0x37, 0xa3, 0x11, 0xfc, 0x3b, 0xe3, 0x77, 0x32, 0x7e, 0xa9, 0xc2, 0xdc, 0xcb, 0xad, 0xbf, 0xe7, 0xd1, 0xd6, 0x98, 0xb0, 0x83, 0xdf, 0x8e, 0x46, 0xf0, 0xef, 0x8c, 0xdf, 0xc9, 0xf8,
0xa1, 0x38, 0x6e, 0xb7, 0xe8, 0x8a, 0x70, 0x07, 0x6e, 0x31, 0x18, 0x0d, 0x0f, 0xdc, 0x62, 0x48, 0xa5, 0x0a, 0x73, 0x2f, 0x77, 0x47, 0xe2, 0xb8, 0xdd, 0xa2, 0x2b, 0xc2, 0x1d, 0xba, 0xc5, 0x60,
0x48, 0x2c, 0x4c, 0xed, 0x3c, 0x03, 0x90, 0x3b, 0xbd, 0xb7, 0xb2, 0x84, 0xd5, 0x7e, 0x17, 0xad, 0x34, 0x3c, 0x74, 0x8b, 0x21, 0x21, 0xb1, 0x30, 0xb3, 0xf7, 0x18, 0x40, 0xee, 0xf6, 0x5f, 0xc9,
0x05, 0x3a, 0x50, 0x25, 0xb5, 0xdf, 0xad, 0xf5, 0xac, 0xcc, 0xcb, 0xc8, 0xfe, 0x7c, 0x86, 0xe4, 0x12, 0x56, 0x07, 0x3d, 0xb4, 0x11, 0xe8, 0x40, 0x95, 0xd5, 0x41, 0xaf, 0xde, 0xb7, 0x32, 0x2f,
0x5b, 0xb3, 0x84, 0xc0, 0x1a, 0xd8, 0xa9, 0x40, 0x66, 0x40, 0x2d, 0x91, 0x10, 0x0a, 0xdd, 0x0c, 0x23, 0xf7, 0xf3, 0x39, 0x92, 0x6f, 0xcd, 0x13, 0x02, 0x6b, 0x60, 0xaf, 0x0a, 0x99, 0x21, 0xb5,
0xe5, 0x41, 0xfa, 0xf9, 0x3e, 0x46, 0x0b, 0x0e, 0x23, 0x32, 0xba, 0xf3, 0x09, 0x40, 0xd3, 0x50, 0x44, 0x42, 0x28, 0x74, 0x27, 0x94, 0x07, 0xe9, 0xe7, 0xfb, 0x18, 0x2d, 0x39, 0x8c, 0xc8, 0xe8,
0x24, 0x1a, 0xc3, 0xa1, 0xf5, 0x00, 0x9f, 0xe7, 0x0a, 0xee, 0xb4, 0x6c, 0x1e, 0x7f, 0xc1, 0x84, 0xde, 0x27, 0x00, 0x2d, 0x43, 0x91, 0x68, 0x0c, 0x87, 0x36, 0x03, 0x7c, 0x9e, 0x28, 0xb8, 0xdb,
0x69, 0x1a, 0x0a, 0x8d, 0xf4, 0x76, 0x7e, 0x04, 0x69, 0x2a, 0xcc, 0x89, 0x85, 0x37, 0x8a, 0x9e, 0xb6, 0x79, 0xfc, 0x05, 0x13, 0xa6, 0x65, 0x28, 0x34, 0xd2, 0xdb, 0xfb, 0x11, 0xa4, 0xa9, 0x30,
0xc9, 0x40, 0x57, 0x4f, 0x46, 0x76, 0x4a, 0x30, 0x4f, 0x19, 0xb0, 0xac, 0x11, 0x6d, 0x04, 0x58, 0x67, 0x16, 0xde, 0x38, 0x7a, 0x26, 0x03, 0x5d, 0x3d, 0x19, 0xd9, 0x2b, 0xc3, 0x22, 0x65, 0xc0,
0x1c, 0xd0, 0x11, 0x1f, 0x93, 0x39, 0x42, 0xc6, 0xc6, 0x76, 0x0a, 0x30, 0x67, 0xb3, 0x31, 0xdf, 0xb2, 0x46, 0xb4, 0x15, 0x60, 0x71, 0x44, 0x47, 0x7c, 0x4c, 0x16, 0x08, 0x19, 0x1b, 0xdb, 0x2b,
0x6a, 0x2d, 0x74, 0x23, 0x84, 0x8b, 0x35, 0xe0, 0x63, 0x92, 0x66, 0x4c, 0xac, 0xa1, 0x81, 0x28, 0xc2, 0x82, 0xcd, 0xc6, 0x7c, 0xa5, 0xb5, 0xd1, 0xed, 0x10, 0x2e, 0xd6, 0x80, 0x8f, 0x49, 0x9a,
0xf6, 0x3f, 0x9b, 0x06, 0x45, 0x61, 0x99, 0x5d, 0xa8, 0x28, 0x6c, 0xac, 0x90, 0x7c, 0x13, 0x6f, 0x31, 0xb1, 0x86, 0x86, 0xa2, 0xd8, 0xff, 0x67, 0x1a, 0x14, 0x85, 0x65, 0x76, 0xa1, 0xa2, 0xb0,
0x1a, 0xca, 0x71, 0x8a, 0x10, 0xfd, 0xe0, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x5e, 0xa7, 0xda, 0xb1, 0x62, 0xf2, 0x65, 0xbc, 0x65, 0x28, 0xa7, 0x29, 0x42, 0xf4, 0x83, 0xff, 0x0b, 0x00, 0x00,
0x94, 0x19, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x2e, 0xde, 0xed, 0x1d, 0x14, 0x3d, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.

View File

@@ -105,14 +105,18 @@ with higher verbosity means more (and less important) logs will be generated.
There are implementations for the following logging libraries: There are implementations for the following logging libraries:
- **a function** (can bridge to non-structured libraries): [funcr](https://github.com/go-logr/logr/tree/master/funcr) - **a function** (can bridge to non-structured libraries): [funcr](https://github.com/go-logr/logr/tree/master/funcr)
- **a testing.T** (for use in Go tests, with JSON-like output): [testr](https://github.com/go-logr/logr/tree/master/testr)
- **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr) - **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr)
- **k8s.io/klog** (for Kubernetes): [klogr](https://git.k8s.io/klog/klogr) - **k8s.io/klog** (for Kubernetes): [klogr](https://git.k8s.io/klog/klogr)
- **a testing.T** (with klog-like text output): [ktesting](https://git.k8s.io/klog/ktesting)
- **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr) - **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr)
- **log** (the Go standard library logger): [stdr](https://github.com/go-logr/stdr) - **log** (the Go standard library logger): [stdr](https://github.com/go-logr/stdr)
- **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr) - **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
- **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend) - **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend)
- **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr) - **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr)
- **github.com/rs/zerolog**: [zerologr](https://github.com/go-logr/zerologr) - **github.com/rs/zerolog**: [zerologr](https://github.com/go-logr/zerologr)
- **github.com/go-kit/log**: [gokitlogr](https://github.com/tonglil/gokitlogr) (also compatible with github.com/go-kit/kit/log since v0.12.0)
- **bytes.Buffer** (writing to a buffer): [bufrlogr](https://github.com/tonglil/buflogr) (useful for ensuring values were logged, like during testing)
## FAQ ## FAQ

View File

@@ -43,7 +43,9 @@ limitations under the License.
// //
// Info() and Error() are very similar, but they are separate methods so that // Info() and Error() are very similar, but they are separate methods so that
// LogSink implementations can choose to do things like attach additional // LogSink implementations can choose to do things like attach additional
// information (such as stack traces) on calls to Error(). // information (such as stack traces) on calls to Error(). Error() messages are
// always logged, regardless of the current verbosity. If there is no error
// instance available, passing nil is valid.
// //
// Verbosity // Verbosity
// //
@@ -53,6 +55,7 @@ limitations under the License.
// Log-lines with V-levels that are not enabled (as per the LogSink) will not // Log-lines with V-levels that are not enabled (as per the LogSink) will not
// be written. Level V(0) is the default, and logger.V(0).Info() has the same // be written. Level V(0) is the default, and logger.V(0).Info() has the same
// meaning as logger.Info(). Negative V-levels have the same meaning as V(0). // meaning as logger.Info(). Negative V-levels have the same meaning as V(0).
// Error messages do not have a verbosity level and are always logged.
// //
// Where we might have written: // Where we might have written:
// if flVerbose >= 2 { // if flVerbose >= 2 {
@@ -112,6 +115,15 @@ limitations under the License.
// may be any Go value, but how the value is formatted is determined by the // may be any Go value, but how the value is formatted is determined by the
// LogSink implementation. // LogSink implementation.
// //
// Logger instances are meant to be passed around by value. Code that receives
// such a value can call its methods without having to check whether the
// instance is ready for use.
//
// Calling methods with the null logger (Logger{}) as instance will crash
// because it has no LogSink. Therefore this null logger should never be passed
// around. For cases where passing a logger is optional, a pointer to Logger
// should be used.
//
// Key Naming Conventions // Key Naming Conventions
// //
// Keys are not strictly required to conform to any specification or regex, but // Keys are not strictly required to conform to any specification or regex, but
@@ -253,11 +265,13 @@ func (l Logger) Info(msg string, keysAndValues ...interface{}) {
// Error logs an error, with the given message and key/value pairs as context. // Error logs an error, with the given message and key/value pairs as context.
// It functions similarly to Info, but may have unique behavior, and should be // It functions similarly to Info, but may have unique behavior, and should be
// preferred for logging errors (see the package documentations for more // preferred for logging errors (see the package documentations for more
// information). // information). The log message will always be emitted, regardless of
// verbosity level.
// //
// The msg argument should be used to add context to any underlying error, // The msg argument should be used to add context to any underlying error,
// while the err argument should be used to attach the actual error that // while the err argument should be used to attach the actual error that
// triggered this log line, if present. // triggered this log line, if present. The err parameter is optional
// and nil may be passed instead of an error instance.
func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) { func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok { if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
withHelper.GetCallStackHelper()() withHelper.GetCallStackHelper()()

524
vendor/github.com/golang/protobuf/jsonpb/decode.go generated vendored Normal file
View File

@@ -0,0 +1,524 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package jsonpb
import (
"encoding/json"
"errors"
"fmt"
"io"
"math"
"reflect"
"strconv"
"strings"
"time"
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/encoding/protojson"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
)
const wrapJSONUnmarshalV2 = false
// UnmarshalNext unmarshals the next JSON object from d into m.
func UnmarshalNext(d *json.Decoder, m proto.Message) error {
return new(Unmarshaler).UnmarshalNext(d, m)
}
// Unmarshal unmarshals a JSON object from r into m.
func Unmarshal(r io.Reader, m proto.Message) error {
return new(Unmarshaler).Unmarshal(r, m)
}
// UnmarshalString unmarshals a JSON object from s into m.
func UnmarshalString(s string, m proto.Message) error {
return new(Unmarshaler).Unmarshal(strings.NewReader(s), m)
}
// Unmarshaler is a configurable object for converting from a JSON
// representation to a protocol buffer object.
type Unmarshaler struct {
// AllowUnknownFields specifies whether to allow messages to contain
// unknown JSON fields, as opposed to failing to unmarshal.
AllowUnknownFields bool
// AnyResolver is used to resolve the google.protobuf.Any well-known type.
// If unset, the global registry is used by default.
AnyResolver AnyResolver
}
// JSONPBUnmarshaler is implemented by protobuf messages that customize the way
// they are unmarshaled from JSON. Messages that implement this should also
// implement JSONPBMarshaler so that the custom format can be produced.
//
// The JSON unmarshaling must follow the JSON to proto specification:
// https://developers.google.com/protocol-buffers/docs/proto3#json
//
// Deprecated: Custom types should implement protobuf reflection instead.
type JSONPBUnmarshaler interface {
UnmarshalJSONPB(*Unmarshaler, []byte) error
}
// Unmarshal unmarshals a JSON object from r into m.
func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error {
return u.UnmarshalNext(json.NewDecoder(r), m)
}
// UnmarshalNext unmarshals the next JSON object from d into m.
func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error {
if m == nil {
return errors.New("invalid nil message")
}
// Parse the next JSON object from the stream.
raw := json.RawMessage{}
if err := d.Decode(&raw); err != nil {
return err
}
// Check for custom unmarshalers first since they may not properly
// implement protobuf reflection that the logic below relies on.
if jsu, ok := m.(JSONPBUnmarshaler); ok {
return jsu.UnmarshalJSONPB(u, raw)
}
mr := proto.MessageReflect(m)
// NOTE: For historical reasons, a top-level null is treated as a noop.
// This is incorrect, but kept for compatibility.
if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" {
return nil
}
if wrapJSONUnmarshalV2 {
// NOTE: If input message is non-empty, we need to preserve merge semantics
// of the old jsonpb implementation. These semantics are not supported by
// the protobuf JSON specification.
isEmpty := true
mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool {
isEmpty = false // at least one iteration implies non-empty
return false
})
if !isEmpty {
// Perform unmarshaling into a newly allocated, empty message.
mr = mr.New()
// Use a defer to copy all unmarshaled fields into the original message.
dst := proto.MessageReflect(m)
defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
dst.Set(fd, v)
return true
})
}
// Unmarshal using the v2 JSON unmarshaler.
opts := protojson.UnmarshalOptions{
DiscardUnknown: u.AllowUnknownFields,
}
if u.AnyResolver != nil {
opts.Resolver = anyResolver{u.AnyResolver}
}
return opts.Unmarshal(raw, mr.Interface())
} else {
if err := u.unmarshalMessage(mr, raw); err != nil {
return err
}
return protoV2.CheckInitialized(mr.Interface())
}
}
func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error {
md := m.Descriptor()
fds := md.Fields()
if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok {
return jsu.UnmarshalJSONPB(u, in)
}
if string(in) == "null" && md.FullName() != "google.protobuf.Value" {
return nil
}
switch wellKnownType(md.FullName()) {
case "Any":
var jsonObject map[string]json.RawMessage
if err := json.Unmarshal(in, &jsonObject); err != nil {
return err
}
rawTypeURL, ok := jsonObject["@type"]
if !ok {
return errors.New("Any JSON doesn't have '@type'")
}
typeURL, err := unquoteString(string(rawTypeURL))
if err != nil {
return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL)
}
m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL))
var m2 protoreflect.Message
if u.AnyResolver != nil {
mi, err := u.AnyResolver.Resolve(typeURL)
if err != nil {
return err
}
m2 = proto.MessageReflect(mi)
} else {
mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
if err != nil {
if err == protoregistry.NotFound {
return fmt.Errorf("could not resolve Any message type: %v", typeURL)
}
return err
}
m2 = mt.New()
}
if wellKnownType(m2.Descriptor().FullName()) != "" {
rawValue, ok := jsonObject["value"]
if !ok {
return errors.New("Any JSON doesn't have 'value'")
}
if err := u.unmarshalMessage(m2, rawValue); err != nil {
return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err)
}
} else {
delete(jsonObject, "@type")
rawJSON, err := json.Marshal(jsonObject)
if err != nil {
return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err)
}
if err = u.unmarshalMessage(m2, rawJSON); err != nil {
return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err)
}
}
rawWire, err := protoV2.Marshal(m2.Interface())
if err != nil {
return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err)
}
m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire))
return nil
case "BoolValue", "BytesValue", "StringValue",
"Int32Value", "UInt32Value", "FloatValue",
"Int64Value", "UInt64Value", "DoubleValue":
fd := fds.ByNumber(1)
v, err := u.unmarshalValue(m.NewField(fd), in, fd)
if err != nil {
return err
}
m.Set(fd, v)
return nil
case "Duration":
v, err := unquoteString(string(in))
if err != nil {
return err
}
d, err := time.ParseDuration(v)
if err != nil {
return fmt.Errorf("bad Duration: %v", err)
}
sec := d.Nanoseconds() / 1e9
nsec := d.Nanoseconds() % 1e9
m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec)))
m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec)))
return nil
case "Timestamp":
v, err := unquoteString(string(in))
if err != nil {
return err
}
t, err := time.Parse(time.RFC3339Nano, v)
if err != nil {
return fmt.Errorf("bad Timestamp: %v", err)
}
sec := t.Unix()
nsec := t.Nanosecond()
m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec)))
m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec)))
return nil
case "Value":
switch {
case string(in) == "null":
m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0))
case string(in) == "true":
m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true))
case string(in) == "false":
m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false))
case hasPrefixAndSuffix('"', in, '"'):
s, err := unquoteString(string(in))
if err != nil {
return fmt.Errorf("unrecognized type for Value %q", in)
}
m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s))
case hasPrefixAndSuffix('[', in, ']'):
v := m.Mutable(fds.ByNumber(6))
return u.unmarshalMessage(v.Message(), in)
case hasPrefixAndSuffix('{', in, '}'):
v := m.Mutable(fds.ByNumber(5))
return u.unmarshalMessage(v.Message(), in)
default:
f, err := strconv.ParseFloat(string(in), 0)
if err != nil {
return fmt.Errorf("unrecognized type for Value %q", in)
}
m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f))
}
return nil
case "ListValue":
var jsonArray []json.RawMessage
if err := json.Unmarshal(in, &jsonArray); err != nil {
return fmt.Errorf("bad ListValue: %v", err)
}
lv := m.Mutable(fds.ByNumber(1)).List()
for _, raw := range jsonArray {
ve := lv.NewElement()
if err := u.unmarshalMessage(ve.Message(), raw); err != nil {
return err
}
lv.Append(ve)
}
return nil
case "Struct":
var jsonObject map[string]json.RawMessage
if err := json.Unmarshal(in, &jsonObject); err != nil {
return fmt.Errorf("bad StructValue: %v", err)
}
mv := m.Mutable(fds.ByNumber(1)).Map()
for key, raw := range jsonObject {
kv := protoreflect.ValueOf(key).MapKey()
vv := mv.NewValue()
if err := u.unmarshalMessage(vv.Message(), raw); err != nil {
return fmt.Errorf("bad value in StructValue for key %q: %v", key, err)
}
mv.Set(kv, vv)
}
return nil
}
var jsonObject map[string]json.RawMessage
if err := json.Unmarshal(in, &jsonObject); err != nil {
return err
}
// Handle known fields.
for i := 0; i < fds.Len(); i++ {
fd := fds.Get(i)
if fd.IsWeak() && fd.Message().IsPlaceholder() {
continue // weak reference is not linked in
}
// Search for any raw JSON value associated with this field.
var raw json.RawMessage
name := string(fd.Name())
if fd.Kind() == protoreflect.GroupKind {
name = string(fd.Message().Name())
}
if v, ok := jsonObject[name]; ok {
delete(jsonObject, name)
raw = v
}
name = string(fd.JSONName())
if v, ok := jsonObject[name]; ok {
delete(jsonObject, name)
raw = v
}
field := m.NewField(fd)
// Unmarshal the field value.
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) {
continue
}
v, err := u.unmarshalValue(field, raw, fd)
if err != nil {
return err
}
m.Set(fd, v)
}
// Handle extension fields.
for name, raw := range jsonObject {
if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") {
continue
}
// Resolve the extension field by name.
xname := protoreflect.FullName(name[len("[") : len(name)-len("]")])
xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
if xt == nil && isMessageSet(md) {
xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
}
if xt == nil {
continue
}
delete(jsonObject, name)
fd := xt.TypeDescriptor()
if fd.ContainingMessage().FullName() != m.Descriptor().FullName() {
return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName())
}
field := m.NewField(fd)
// Unmarshal the field value.
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) {
continue
}
v, err := u.unmarshalValue(field, raw, fd)
if err != nil {
return err
}
m.Set(fd, v)
}
if !u.AllowUnknownFields && len(jsonObject) > 0 {
for name := range jsonObject {
return fmt.Errorf("unknown field %q in %v", name, md.FullName())
}
}
return nil
}
func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool {
if md := fd.Message(); md != nil {
return md.FullName() == "google.protobuf.Value" && fd.Cardinality() != protoreflect.Repeated
}
return false
}
func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool {
if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated {
_, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler)
return ok
}
return false
}
func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
switch {
case fd.IsList():
var jsonArray []json.RawMessage
if err := json.Unmarshal(in, &jsonArray); err != nil {
return v, err
}
lv := v.List()
for _, raw := range jsonArray {
ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd)
if err != nil {
return v, err
}
lv.Append(ve)
}
return v, nil
case fd.IsMap():
var jsonObject map[string]json.RawMessage
if err := json.Unmarshal(in, &jsonObject); err != nil {
return v, err
}
kfd := fd.MapKey()
vfd := fd.MapValue()
mv := v.Map()
for key, raw := range jsonObject {
var kv protoreflect.MapKey
if kfd.Kind() == protoreflect.StringKind {
kv = protoreflect.ValueOf(key).MapKey()
} else {
v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd)
if err != nil {
return v, err
}
kv = v.MapKey()
}
vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd)
if err != nil {
return v, err
}
mv.Set(kv, vv)
}
return v, nil
default:
return u.unmarshalSingularValue(v, in, fd)
}
}
var nonFinite = map[string]float64{
`"NaN"`: math.NaN(),
`"Infinity"`: math.Inf(+1),
`"-Infinity"`: math.Inf(-1),
}
func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
switch fd.Kind() {
case protoreflect.BoolKind:
return unmarshalValue(in, new(bool))
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
return unmarshalValue(trimQuote(in), new(int32))
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return unmarshalValue(trimQuote(in), new(int64))
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
return unmarshalValue(trimQuote(in), new(uint32))
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return unmarshalValue(trimQuote(in), new(uint64))
case protoreflect.FloatKind:
if f, ok := nonFinite[string(in)]; ok {
return protoreflect.ValueOfFloat32(float32(f)), nil
}
return unmarshalValue(trimQuote(in), new(float32))
case protoreflect.DoubleKind:
if f, ok := nonFinite[string(in)]; ok {
return protoreflect.ValueOfFloat64(float64(f)), nil
}
return unmarshalValue(trimQuote(in), new(float64))
case protoreflect.StringKind:
return unmarshalValue(in, new(string))
case protoreflect.BytesKind:
return unmarshalValue(in, new([]byte))
case protoreflect.EnumKind:
if hasPrefixAndSuffix('"', in, '"') {
vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in)))
if vd == nil {
return v, fmt.Errorf("unknown value %q for enum %s", in, fd.Enum().FullName())
}
return protoreflect.ValueOfEnum(vd.Number()), nil
}
return unmarshalValue(in, new(protoreflect.EnumNumber))
case protoreflect.MessageKind, protoreflect.GroupKind:
err := u.unmarshalMessage(v.Message(), in)
return v, err
default:
panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
}
}
func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) {
err := json.Unmarshal(in, v)
return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err
}
func unquoteString(in string) (out string, err error) {
err = json.Unmarshal([]byte(in), &out)
return out, err
}
func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool {
if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix {
return true
}
return false
}
// trimQuote is like unquoteString but simply strips surrounding quotes.
// This is incorrect, but is behavior done by the legacy implementation.
func trimQuote(in []byte) []byte {
if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' {
in = in[1 : len(in)-1]
}
return in
}

559
vendor/github.com/golang/protobuf/jsonpb/encode.go generated vendored Normal file
View File

@@ -0,0 +1,559 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package jsonpb
import (
"encoding/json"
"errors"
"fmt"
"io"
"math"
"reflect"
"sort"
"strconv"
"strings"
"time"
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/encoding/protojson"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
)
const wrapJSONMarshalV2 = false
// Marshaler is a configurable object for marshaling protocol buffer messages
// to the specified JSON representation.
type Marshaler struct {
// OrigName specifies whether to use the original protobuf name for fields.
OrigName bool
// EnumsAsInts specifies whether to render enum values as integers,
// as opposed to string values.
EnumsAsInts bool
// EmitDefaults specifies whether to render fields with zero values.
EmitDefaults bool
// Indent controls whether the output is compact or not.
// If empty, the output is compact JSON. Otherwise, every JSON object
// entry and JSON array value will be on its own line.
// Each line will be preceded by repeated copies of Indent, where the
// number of copies is the current indentation depth.
Indent string
// AnyResolver is used to resolve the google.protobuf.Any well-known type.
// If unset, the global registry is used by default.
AnyResolver AnyResolver
}
// JSONPBMarshaler is implemented by protobuf messages that customize the
// way they are marshaled to JSON. Messages that implement this should also
// implement JSONPBUnmarshaler so that the custom format can be parsed.
//
// The JSON marshaling must follow the proto to JSON specification:
// https://developers.google.com/protocol-buffers/docs/proto3#json
//
// Deprecated: Custom types should implement protobuf reflection instead.
type JSONPBMarshaler interface {
MarshalJSONPB(*Marshaler) ([]byte, error)
}
// Marshal serializes a protobuf message as JSON into w.
func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error {
b, err := jm.marshal(m)
if len(b) > 0 {
if _, err := w.Write(b); err != nil {
return err
}
}
return err
}
// MarshalToString serializes a protobuf message as JSON in string form.
func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) {
b, err := jm.marshal(m)
if err != nil {
return "", err
}
return string(b), nil
}
func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) {
v := reflect.ValueOf(m)
if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
return nil, errors.New("Marshal called with nil")
}
// Check for custom marshalers first since they may not properly
// implement protobuf reflection that the logic below relies on.
if jsm, ok := m.(JSONPBMarshaler); ok {
return jsm.MarshalJSONPB(jm)
}
if wrapJSONMarshalV2 {
opts := protojson.MarshalOptions{
UseProtoNames: jm.OrigName,
UseEnumNumbers: jm.EnumsAsInts,
EmitUnpopulated: jm.EmitDefaults,
Indent: jm.Indent,
}
if jm.AnyResolver != nil {
opts.Resolver = anyResolver{jm.AnyResolver}
}
return opts.Marshal(proto.MessageReflect(m).Interface())
} else {
// Check for unpopulated required fields first.
m2 := proto.MessageReflect(m)
if err := protoV2.CheckInitialized(m2.Interface()); err != nil {
return nil, err
}
w := jsonWriter{Marshaler: jm}
err := w.marshalMessage(m2, "", "")
return w.buf, err
}
}
type jsonWriter struct {
*Marshaler
buf []byte
}
func (w *jsonWriter) write(s string) {
w.buf = append(w.buf, s...)
}
func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error {
if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok {
b, err := jsm.MarshalJSONPB(w.Marshaler)
if err != nil {
return err
}
if typeURL != "" {
// we are marshaling this object to an Any type
var js map[string]*json.RawMessage
if err = json.Unmarshal(b, &js); err != nil {
return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err)
}
turl, err := json.Marshal(typeURL)
if err != nil {
return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
}
js["@type"] = (*json.RawMessage)(&turl)
if b, err = json.Marshal(js); err != nil {
return err
}
}
w.write(string(b))
return nil
}
md := m.Descriptor()
fds := md.Fields()
// Handle well-known types.
const secondInNanos = int64(time.Second / time.Nanosecond)
switch wellKnownType(md.FullName()) {
case "Any":
return w.marshalAny(m, indent)
case "BoolValue", "BytesValue", "StringValue",
"Int32Value", "UInt32Value", "FloatValue",
"Int64Value", "UInt64Value", "DoubleValue":
fd := fds.ByNumber(1)
return w.marshalValue(fd, m.Get(fd), indent)
case "Duration":
const maxSecondsInDuration = 315576000000
// "Generated output always contains 0, 3, 6, or 9 fractional digits,
// depending on required precision."
s := m.Get(fds.ByNumber(1)).Int()
ns := m.Get(fds.ByNumber(2)).Int()
if s < -maxSecondsInDuration || s > maxSecondsInDuration {
return fmt.Errorf("seconds out of range %v", s)
}
if ns <= -secondInNanos || ns >= secondInNanos {
return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
}
if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
return errors.New("signs of seconds and nanos do not match")
}
var sign string
if s < 0 || ns < 0 {
sign, s, ns = "-", -1*s, -1*ns
}
x := fmt.Sprintf("%s%d.%09d", sign, s, ns)
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, ".000")
w.write(fmt.Sprintf(`"%vs"`, x))
return nil
case "Timestamp":
// "RFC 3339, where generated output will always be Z-normalized
// and uses 0, 3, 6 or 9 fractional digits."
s := m.Get(fds.ByNumber(1)).Int()
ns := m.Get(fds.ByNumber(2)).Int()
if ns < 0 || ns >= secondInNanos {
return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
}
t := time.Unix(s, ns).UTC()
// time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
x := t.Format("2006-01-02T15:04:05.000000000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, ".000")
w.write(fmt.Sprintf(`"%vZ"`, x))
return nil
case "Value":
// JSON value; which is a null, number, string, bool, object, or array.
od := md.Oneofs().Get(0)
fd := m.WhichOneof(od)
if fd == nil {
return errors.New("nil Value")
}
return w.marshalValue(fd, m.Get(fd), indent)
case "Struct", "ListValue":
// JSON object or array.
fd := fds.ByNumber(1)
return w.marshalValue(fd, m.Get(fd), indent)
}
w.write("{")
if w.Indent != "" {
w.write("\n")
}
firstField := true
if typeURL != "" {
if err := w.marshalTypeURL(indent, typeURL); err != nil {
return err
}
firstField = false
}
for i := 0; i < fds.Len(); {
fd := fds.Get(i)
if od := fd.ContainingOneof(); od != nil {
fd = m.WhichOneof(od)
i += od.Fields().Len()
if fd == nil {
continue
}
} else {
i++
}
v := m.Get(fd)
if !m.Has(fd) {
if !w.EmitDefaults || fd.ContainingOneof() != nil {
continue
}
if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) {
v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars
}
}
if !firstField {
w.writeComma()
}
if err := w.marshalField(fd, v, indent); err != nil {
return err
}
firstField = false
}
// Handle proto2 extensions.
if md.ExtensionRanges().Len() > 0 {
// Collect a sorted list of all extension descriptor and values.
type ext struct {
desc protoreflect.FieldDescriptor
val protoreflect.Value
}
var exts []ext
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
if fd.IsExtension() {
exts = append(exts, ext{fd, v})
}
return true
})
sort.Slice(exts, func(i, j int) bool {
return exts[i].desc.Number() < exts[j].desc.Number()
})
for _, ext := range exts {
if !firstField {
w.writeComma()
}
if err := w.marshalField(ext.desc, ext.val, indent); err != nil {
return err
}
firstField = false
}
}
if w.Indent != "" {
w.write("\n")
w.write(indent)
}
w.write("}")
return nil
}
func (w *jsonWriter) writeComma() {
if w.Indent != "" {
w.write(",\n")
} else {
w.write(",")
}
}
func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error {
// "If the Any contains a value that has a special JSON mapping,
// it will be converted as follows: {"@type": xxx, "value": yyy}.
// Otherwise, the value will be converted into a JSON object,
// and the "@type" field will be inserted to indicate the actual data type."
md := m.Descriptor()
typeURL := m.Get(md.Fields().ByNumber(1)).String()
rawVal := m.Get(md.Fields().ByNumber(2)).Bytes()
var m2 protoreflect.Message
if w.AnyResolver != nil {
mi, err := w.AnyResolver.Resolve(typeURL)
if err != nil {
return err
}
m2 = proto.MessageReflect(mi)
} else {
mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
if err != nil {
return err
}
m2 = mt.New()
}
if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil {
return err
}
if wellKnownType(m2.Descriptor().FullName()) == "" {
return w.marshalMessage(m2, indent, typeURL)
}
w.write("{")
if w.Indent != "" {
w.write("\n")
}
if err := w.marshalTypeURL(indent, typeURL); err != nil {
return err
}
w.writeComma()
if w.Indent != "" {
w.write(indent)
w.write(w.Indent)
w.write(`"value": `)
} else {
w.write(`"value":`)
}
if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil {
return err
}
if w.Indent != "" {
w.write("\n")
w.write(indent)
}
w.write("}")
return nil
}
func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error {
if w.Indent != "" {
w.write(indent)
w.write(w.Indent)
}
w.write(`"@type":`)
if w.Indent != "" {
w.write(" ")
}
b, err := json.Marshal(typeURL)
if err != nil {
return err
}
w.write(string(b))
return nil
}
// marshalField writes field description and value to the Writer.
func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
if w.Indent != "" {
w.write(indent)
w.write(w.Indent)
}
w.write(`"`)
switch {
case fd.IsExtension():
// For message set, use the fname of the message as the extension name.
name := string(fd.FullName())
if isMessageSet(fd.ContainingMessage()) {
name = strings.TrimSuffix(name, ".message_set_extension")
}
w.write("[" + name + "]")
case w.OrigName:
name := string(fd.Name())
if fd.Kind() == protoreflect.GroupKind {
name = string(fd.Message().Name())
}
w.write(name)
default:
w.write(string(fd.JSONName()))
}
w.write(`":`)
if w.Indent != "" {
w.write(" ")
}
return w.marshalValue(fd, v, indent)
}
func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
switch {
case fd.IsList():
w.write("[")
comma := ""
lv := v.List()
for i := 0; i < lv.Len(); i++ {
w.write(comma)
if w.Indent != "" {
w.write("\n")
w.write(indent)
w.write(w.Indent)
w.write(w.Indent)
}
if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil {
return err
}
comma = ","
}
if w.Indent != "" {
w.write("\n")
w.write(indent)
w.write(w.Indent)
}
w.write("]")
return nil
case fd.IsMap():
kfd := fd.MapKey()
vfd := fd.MapValue()
mv := v.Map()
// Collect a sorted list of all map keys and values.
type entry struct{ key, val protoreflect.Value }
var entries []entry
mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
entries = append(entries, entry{k.Value(), v})
return true
})
sort.Slice(entries, func(i, j int) bool {
switch kfd.Kind() {
case protoreflect.BoolKind:
return !entries[i].key.Bool() && entries[j].key.Bool()
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return entries[i].key.Int() < entries[j].key.Int()
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return entries[i].key.Uint() < entries[j].key.Uint()
case protoreflect.StringKind:
return entries[i].key.String() < entries[j].key.String()
default:
panic("invalid kind")
}
})
w.write(`{`)
comma := ""
for _, entry := range entries {
w.write(comma)
if w.Indent != "" {
w.write("\n")
w.write(indent)
w.write(w.Indent)
w.write(w.Indent)
}
s := fmt.Sprint(entry.key.Interface())
b, err := json.Marshal(s)
if err != nil {
return err
}
w.write(string(b))
w.write(`:`)
if w.Indent != "" {
w.write(` `)
}
if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil {
return err
}
comma = ","
}
if w.Indent != "" {
w.write("\n")
w.write(indent)
w.write(w.Indent)
}
w.write(`}`)
return nil
default:
return w.marshalSingularValue(fd, v, indent)
}
}
func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
switch {
case !v.IsValid():
w.write("null")
return nil
case fd.Message() != nil:
return w.marshalMessage(v.Message(), indent+w.Indent, "")
case fd.Enum() != nil:
if fd.Enum().FullName() == "google.protobuf.NullValue" {
w.write("null")
return nil
}
vd := fd.Enum().Values().ByNumber(v.Enum())
if vd == nil || w.EnumsAsInts {
w.write(strconv.Itoa(int(v.Enum())))
} else {
w.write(`"` + string(vd.Name()) + `"`)
}
return nil
default:
switch v.Interface().(type) {
case float32, float64:
switch {
case math.IsInf(v.Float(), +1):
w.write(`"Infinity"`)
return nil
case math.IsInf(v.Float(), -1):
w.write(`"-Infinity"`)
return nil
case math.IsNaN(v.Float()):
w.write(`"NaN"`)
return nil
}
case int64, uint64:
w.write(fmt.Sprintf(`"%d"`, v.Interface()))
return nil
}
b, err := json.Marshal(v.Interface())
if err != nil {
return err
}
w.write(string(b))
return nil
}
}

69
vendor/github.com/golang/protobuf/jsonpb/json.go generated vendored Normal file
View File

@@ -0,0 +1,69 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package jsonpb provides functionality to marshal and unmarshal between a
// protocol buffer message and JSON. It follows the specification at
// https://developers.google.com/protocol-buffers/docs/proto3#json.
//
// Do not rely on the default behavior of the standard encoding/json package
// when called on generated message types as it does not operate correctly.
//
// Deprecated: Use the "google.golang.org/protobuf/encoding/protojson"
// package instead.
package jsonpb
import (
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)
// AnyResolver takes a type URL, present in an Any message,
// and resolves it into an instance of the associated message.
type AnyResolver interface {
Resolve(typeURL string) (proto.Message, error)
}
type anyResolver struct{ AnyResolver }
func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
return r.FindMessageByURL(string(message))
}
func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) {
m, err := r.Resolve(url)
if err != nil {
return nil, err
}
return protoimpl.X.MessageTypeOf(m), nil
}
func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
return protoregistry.GlobalTypes.FindExtensionByName(field)
}
func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
return protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
}
func wellKnownType(s protoreflect.FullName) string {
if s.Parent() == "google.protobuf" {
switch s.Name() {
case "Empty", "Any",
"BoolValue", "BytesValue", "StringValue",
"Int32Value", "UInt32Value", "FloatValue",
"Int64Value", "UInt64Value", "DoubleValue",
"Duration", "Timestamp",
"NullValue", "Struct", "Value", "ListValue":
return string(s.Name())
}
}
return ""
}
func isMessageSet(md protoreflect.MessageDescriptor) bool {
ms, ok := md.(interface{ IsMessageSet() bool })
return ok && ms.IsMessageSet()
}

3
vendor/golang.org/x/net/AUTHORS generated vendored
View File

@@ -1,3 +0,0 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at http://tip.golang.org/AUTHORS.

View File

@@ -1,3 +0,0 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at http://tip.golang.org/CONTRIBUTORS.

View File

@@ -21,9 +21,9 @@
// explicitly to each function that needs it. The Context should be the first // explicitly to each function that needs it. The Context should be the first
// parameter, typically named ctx: // parameter, typically named ctx:
// //
// func DoSomething(ctx context.Context, arg Arg) error { // func DoSomething(ctx context.Context, arg Arg) error {
// // ... use ctx ... // // ... use ctx ...
// } // }
// //
// Do not pass a nil Context, even if a function permits it. Pass context.TODO // Do not pass a nil Context, even if a function permits it. Pass context.TODO
// if you are unsure about which Context to use. // if you are unsure about which Context to use.

View File

@@ -54,11 +54,11 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
// Canceling this context releases resources associated with it, so code should // Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete: // call cancel as soon as the operations running in this Context complete:
// //
// func slowOperationWithTimeout(ctx context.Context) (Result, error) { // func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// defer cancel() // releases resources if slowOperation completes before timeout elapses // defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx) // return slowOperation(ctx)
// } // }
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout)) return WithDeadline(parent, time.Now().Add(timeout))
} }

View File

@@ -264,11 +264,11 @@ func (c *timerCtx) cancel(removeFromParent bool, err error) {
// Canceling this context releases resources associated with it, so code should // Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete: // call cancel as soon as the operations running in this Context complete:
// //
// func slowOperationWithTimeout(ctx context.Context) (Result, error) { // func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// defer cancel() // releases resources if slowOperation completes before timeout elapses // defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx) // return slowOperation(ctx)
// } // }
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout)) return WithDeadline(parent, time.Now().Add(timeout))
} }

View File

@@ -173,13 +173,15 @@ func tokenEqual(t1, t2 string) bool {
// isLWS reports whether b is linear white space, according // isLWS reports whether b is linear white space, according
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 // to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
// LWS = [CRLF] 1*( SP | HT ) //
// LWS = [CRLF] 1*( SP | HT )
func isLWS(b byte) bool { return b == ' ' || b == '\t' } func isLWS(b byte) bool { return b == ' ' || b == '\t' }
// isCTL reports whether b is a control byte, according // isCTL reports whether b is a control byte, according
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 // to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
// CTL = <any US-ASCII control character //
// (octets 0 - 31) and DEL (127)> // CTL = <any US-ASCII control character
// (octets 0 - 31) and DEL (127)>
func isCTL(b byte) bool { func isCTL(b byte) bool {
const del = 0x7f // a CTL const del = 0x7f // a CTL
return b < ' ' || b == del return b < ' ' || b == del
@@ -189,12 +191,13 @@ func isCTL(b byte) bool {
// HTTP/2 imposes the additional restriction that uppercase ASCII // HTTP/2 imposes the additional restriction that uppercase ASCII
// letters are not allowed. // letters are not allowed.
// //
// RFC 7230 says: // RFC 7230 says:
// header-field = field-name ":" OWS field-value OWS //
// field-name = token // header-field = field-name ":" OWS field-value OWS
// token = 1*tchar // field-name = token
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / // token = 1*tchar
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA // tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
func ValidHeaderFieldName(v string) bool { func ValidHeaderFieldName(v string) bool {
if len(v) == 0 { if len(v) == 0 {
return false return false
@@ -267,27 +270,28 @@ var validHostByte = [256]bool{
// ValidHeaderFieldValue reports whether v is a valid "field-value" according to // ValidHeaderFieldValue reports whether v is a valid "field-value" according to
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 : // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
// //
// message-header = field-name ":" [ field-value ] // message-header = field-name ":" [ field-value ]
// field-value = *( field-content | LWS ) // field-value = *( field-content | LWS )
// field-content = <the OCTETs making up the field-value // field-content = <the OCTETs making up the field-value
// and consisting of either *TEXT or combinations // and consisting of either *TEXT or combinations
// of token, separators, and quoted-string> // of token, separators, and quoted-string>
// //
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 : // http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
// //
// TEXT = <any OCTET except CTLs, // TEXT = <any OCTET except CTLs,
// but including LWS> // but including LWS>
// LWS = [CRLF] 1*( SP | HT ) // LWS = [CRLF] 1*( SP | HT )
// CTL = <any US-ASCII control character // CTL = <any US-ASCII control character
// (octets 0 - 31) and DEL (127)> // (octets 0 - 31) and DEL (127)>
// //
// RFC 7230 says: // RFC 7230 says:
// field-value = *( field-content / obs-fold ) //
// obj-fold = N/A to http2, and deprecated // field-value = *( field-content / obs-fold )
// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] // obj-fold = N/A to http2, and deprecated
// field-vchar = VCHAR / obs-text // field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
// obs-text = %x80-FF // field-vchar = VCHAR / obs-text
// VCHAR = "any visible [USASCII] character" // obs-text = %x80-FF
// VCHAR = "any visible [USASCII] character"
// //
// http2 further says: "Similarly, HTTP/2 allows header field values // http2 further says: "Similarly, HTTP/2 allows header field values
// that are not valid. While most of the values that can be encoded // that are not valid. While most of the values that can be encoded

View File

@@ -139,7 +139,6 @@ func (p *clientConnPool) getStartDialLocked(ctx context.Context, addr string) *d
func (c *dialCall) dial(ctx context.Context, addr string) { func (c *dialCall) dial(ctx context.Context, addr string) {
const singleUse = false // shared conn const singleUse = false // shared conn
c.res, c.err = c.p.t.dialClientConn(ctx, addr, singleUse) c.res, c.err = c.p.t.dialClientConn(ctx, addr, singleUse)
close(c.done)
c.p.mu.Lock() c.p.mu.Lock()
delete(c.p.dialing, addr) delete(c.p.dialing, addr)
@@ -147,6 +146,8 @@ func (c *dialCall) dial(ctx context.Context, addr string) {
c.p.addConnLocked(addr, c.res) c.p.addConnLocked(addr, c.res)
} }
c.p.mu.Unlock() c.p.mu.Unlock()
close(c.done)
} }
// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't // addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't

View File

@@ -136,7 +136,7 @@ func (e headerFieldNameError) Error() string {
type headerFieldValueError string type headerFieldValueError string
func (e headerFieldValueError) Error() string { func (e headerFieldValueError) Error() string {
return fmt.Sprintf("invalid header field value %q", string(e)) return fmt.Sprintf("invalid header field value for %q", string(e))
} }
var ( var (

View File

@@ -1532,7 +1532,8 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
fr.debugReadLoggerf("http2: decoded hpack field %+v", hf) fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
} }
if !httpguts.ValidHeaderFieldValue(hf.Value) { if !httpguts.ValidHeaderFieldValue(hf.Value) {
invalid = headerFieldValueError(hf.Value) // Don't include the value in the error, because it may be sensitive.
invalid = headerFieldValueError(hf.Name)
} }
isPseudo := strings.HasPrefix(hf.Name, ":") isPseudo := strings.HasPrefix(hf.Name, ":")
if isPseudo { if isPseudo {

View File

@@ -169,25 +169,50 @@ func buildRootHuffmanNode() {
// AppendHuffmanString appends s, as encoded in Huffman codes, to dst // AppendHuffmanString appends s, as encoded in Huffman codes, to dst
// and returns the extended buffer. // and returns the extended buffer.
func AppendHuffmanString(dst []byte, s string) []byte { func AppendHuffmanString(dst []byte, s string) []byte {
rembits := uint8(8) // This relies on the maximum huffman code length being 30 (See tables.go huffmanCodeLen array)
// So if a uint64 buffer has less than 32 valid bits can always accommodate another huffmanCode.
var (
x uint64 // buffer
n uint // number valid of bits present in x
)
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
if rembits == 8 { c := s[i]
dst = append(dst, 0) n += uint(huffmanCodeLen[c])
x <<= huffmanCodeLen[c] % 64
x |= uint64(huffmanCodes[c])
if n >= 32 {
n %= 32 // Normally would be -= 32 but %= 32 informs compiler 0 <= n <= 31 for upcoming shift
y := uint32(x >> n) // Compiler doesn't combine memory writes if y isn't uint32
dst = append(dst, byte(y>>24), byte(y>>16), byte(y>>8), byte(y))
} }
dst, rembits = appendByteToHuffmanCode(dst, rembits, s[i])
} }
// Add padding bits if necessary
if rembits < 8 { if over := n % 8; over > 0 {
// special EOS symbol const (
code := uint32(0x3fffffff) eosCode = 0x3fffffff
nbits := uint8(30) eosNBits = 30
eosPadByte = eosCode >> (eosNBits - 8)
t := uint8(code >> (nbits - rembits)) )
dst[len(dst)-1] |= t pad := 8 - over
x = (x << pad) | (eosPadByte >> over)
n += pad // 8 now divides into n exactly
} }
// n in (0, 8, 16, 24, 32)
return dst switch n / 8 {
case 0:
return dst
case 1:
return append(dst, byte(x))
case 2:
y := uint16(x)
return append(dst, byte(y>>8), byte(y))
case 3:
y := uint16(x >> 8)
return append(dst, byte(y>>8), byte(y), byte(x))
}
// case 4:
y := uint32(x)
return append(dst, byte(y>>24), byte(y>>16), byte(y>>8), byte(y))
} }
// HuffmanEncodeLength returns the number of bytes required to encode // HuffmanEncodeLength returns the number of bytes required to encode
@@ -199,35 +224,3 @@ func HuffmanEncodeLength(s string) uint64 {
} }
return (n + 7) / 8 return (n + 7) / 8
} }
// appendByteToHuffmanCode appends Huffman code for c to dst and
// returns the extended buffer and the remaining bits in the last
// element. The appending is not byte aligned and the remaining bits
// in the last element of dst is given in rembits.
func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte, uint8) {
code := huffmanCodes[c]
nbits := huffmanCodeLen[c]
for {
if rembits > nbits {
t := uint8(code << (rembits - nbits))
dst[len(dst)-1] |= t
rembits -= nbits
break
}
t := uint8(code >> (nbits - rembits))
dst[len(dst)-1] |= t
nbits -= rembits
rembits = 8
if nbits == 0 {
break
}
dst = append(dst, 0)
}
return dst, rembits
}

View File

@@ -13,7 +13,6 @@
// See https://http2.github.io/ for more information on HTTP/2. // See https://http2.github.io/ for more information on HTTP/2.
// //
// See https://http2.golang.org/ for a test server running this code. // See https://http2.golang.org/ for a test server running this code.
//
package http2 // import "golang.org/x/net/http2" package http2 // import "golang.org/x/net/http2"
import ( import (
@@ -176,10 +175,11 @@ func (s SettingID) String() string {
// name (key). See httpguts.ValidHeaderName for the base rules. // name (key). See httpguts.ValidHeaderName for the base rules.
// //
// Further, http2 says: // Further, http2 says:
// "Just as in HTTP/1.x, header field names are strings of ASCII //
// characters that are compared in a case-insensitive // "Just as in HTTP/1.x, header field names are strings of ASCII
// fashion. However, header field names MUST be converted to // characters that are compared in a case-insensitive
// lowercase prior to their encoding in HTTP/2. " // fashion. However, header field names MUST be converted to
// lowercase prior to their encoding in HTTP/2. "
func validWireHeaderFieldName(v string) bool { func validWireHeaderFieldName(v string) bool {
if len(v) == 0 { if len(v) == 0 {
return false return false
@@ -365,8 +365,8 @@ func (s *sorter) SortStrings(ss []string) {
// validPseudoPath reports whether v is a valid :path pseudo-header // validPseudoPath reports whether v is a valid :path pseudo-header
// value. It must be either: // value. It must be either:
// //
// *) a non-empty string starting with '/' // - a non-empty string starting with '/'
// *) the string '*', for OPTIONS requests. // - the string '*', for OPTIONS requests.
// //
// For now this is only used a quick check for deciding when to clean // For now this is only used a quick check for deciding when to clean
// up Opaque URLs before sending requests from the Transport. // up Opaque URLs before sending requests from the Transport.

View File

@@ -315,6 +315,20 @@ type ServeConnOpts struct {
// requests. If nil, BaseConfig.Handler is used. If BaseConfig // requests. If nil, BaseConfig.Handler is used. If BaseConfig
// or BaseConfig.Handler is nil, http.DefaultServeMux is used. // or BaseConfig.Handler is nil, http.DefaultServeMux is used.
Handler http.Handler Handler http.Handler
// UpgradeRequest is an initial request received on a connection
// undergoing an h2c upgrade. The request body must have been
// completely read from the connection before calling ServeConn,
// and the 101 Switching Protocols response written.
UpgradeRequest *http.Request
// Settings is the decoded contents of the HTTP2-Settings header
// in an h2c upgrade request.
Settings []byte
// SawClientPreface is set if the HTTP/2 connection preface
// has already been read from the connection.
SawClientPreface bool
} }
func (o *ServeConnOpts) context() context.Context { func (o *ServeConnOpts) context() context.Context {
@@ -383,6 +397,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
headerTableSize: initialHeaderTableSize, headerTableSize: initialHeaderTableSize,
serveG: newGoroutineLock(), serveG: newGoroutineLock(),
pushEnabled: true, pushEnabled: true,
sawClientPreface: opts.SawClientPreface,
} }
s.state.registerConn(sc) s.state.registerConn(sc)
@@ -400,7 +415,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
if s.NewWriteScheduler != nil { if s.NewWriteScheduler != nil {
sc.writeSched = s.NewWriteScheduler() sc.writeSched = s.NewWriteScheduler()
} else { } else {
sc.writeSched = NewRandomWriteScheduler() sc.writeSched = NewPriorityWriteScheduler(nil)
} }
// These start at the RFC-specified defaults. If there is a higher // These start at the RFC-specified defaults. If there is a higher
@@ -465,9 +480,27 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
} }
} }
if opts.Settings != nil {
fr := &SettingsFrame{
FrameHeader: FrameHeader{valid: true},
p: opts.Settings,
}
if err := fr.ForeachSetting(sc.processSetting); err != nil {
sc.rejectConn(ErrCodeProtocol, "invalid settings")
return
}
opts.Settings = nil
}
if hook := testHookGetServerConn; hook != nil { if hook := testHookGetServerConn; hook != nil {
hook(sc) hook(sc)
} }
if opts.UpgradeRequest != nil {
sc.upgradeRequest(opts.UpgradeRequest)
opts.UpgradeRequest = nil
}
sc.serve() sc.serve()
} }
@@ -512,6 +545,7 @@ type serverConn struct {
// Everything following is owned by the serve loop; use serveG.check(): // Everything following is owned by the serve loop; use serveG.check():
serveG goroutineLock // used to verify funcs are on serve() serveG goroutineLock // used to verify funcs are on serve()
pushEnabled bool pushEnabled bool
sawClientPreface bool // preface has already been read, used in h2c upgrade
sawFirstSettings bool // got the initial SETTINGS frame after the preface sawFirstSettings bool // got the initial SETTINGS frame after the preface
needToSendSettingsAck bool needToSendSettingsAck bool
unackedSettings int // how many SETTINGS have we sent without ACKs? unackedSettings int // how many SETTINGS have we sent without ACKs?
@@ -974,6 +1008,9 @@ var errPrefaceTimeout = errors.New("timeout waiting for client preface")
// returns errPrefaceTimeout on timeout, or an error if the greeting // returns errPrefaceTimeout on timeout, or an error if the greeting
// is invalid. // is invalid.
func (sc *serverConn) readPreface() error { func (sc *serverConn) readPreface() error {
if sc.sawClientPreface {
return nil
}
errc := make(chan error, 1) errc := make(chan error, 1)
go func() { go func() {
// Read the client preface // Read the client preface
@@ -1915,6 +1952,26 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
return nil return nil
} }
func (sc *serverConn) upgradeRequest(req *http.Request) {
sc.serveG.check()
id := uint32(1)
sc.maxClientStreamID = id
st := sc.newStream(id, 0, stateHalfClosedRemote)
st.reqTrailer = req.Trailer
if st.reqTrailer != nil {
st.trailer = make(http.Header)
}
rw := sc.newResponseWriter(st, req)
// Disable any read deadline set by the net/http package
// prior to the upgrade.
if sc.hs.ReadTimeout != 0 {
sc.conn.SetReadDeadline(time.Time{})
}
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
}
func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error { func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
sc := st.sc sc := st.sc
sc.serveG.check() sc.serveG.check()
@@ -2145,6 +2202,11 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
} }
req = req.WithContext(st.ctx) req = req.WithContext(st.ctx)
rw := sc.newResponseWriter(st, req)
return rw, req, nil
}
func (sc *serverConn) newResponseWriter(st *stream, req *http.Request) *responseWriter {
rws := responseWriterStatePool.Get().(*responseWriterState) rws := responseWriterStatePool.Get().(*responseWriterState)
bwSave := rws.bw bwSave := rws.bw
*rws = responseWriterState{} // zero all the fields *rws = responseWriterState{} // zero all the fields
@@ -2153,10 +2215,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
rws.bw.Reset(chunkWriter{rws}) rws.bw.Reset(chunkWriter{rws})
rws.stream = st rws.stream = st
rws.req = req rws.req = req
rws.body = body return &responseWriter{rws: rws}
rw := &responseWriter{rws: rws}
return rw, req, nil
} }
// Run on its own goroutine. // Run on its own goroutine.
@@ -2316,17 +2375,18 @@ type requestBody struct {
_ incomparable _ incomparable
stream *stream stream *stream
conn *serverConn conn *serverConn
closed bool // for use by Close only closeOnce sync.Once // for use by Close only
sawEOF bool // for use by Read only sawEOF bool // for use by Read only
pipe *pipe // non-nil if we have a HTTP entity message body pipe *pipe // non-nil if we have a HTTP entity message body
needsContinue bool // need to send a 100-continue needsContinue bool // need to send a 100-continue
} }
func (b *requestBody) Close() error { func (b *requestBody) Close() error {
if b.pipe != nil && !b.closed { b.closeOnce.Do(func() {
b.pipe.BreakWithError(errClosedBody) if b.pipe != nil {
} b.pipe.BreakWithError(errClosedBody)
b.closed = true }
})
return nil return nil
} }
@@ -2370,7 +2430,6 @@ type responseWriterState struct {
// immutable within a request: // immutable within a request:
stream *stream stream *stream
req *http.Request req *http.Request
body *requestBody // to close at end of request, if DATA frames didn't
conn *serverConn conn *serverConn
// TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc // TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
@@ -2546,8 +2605,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
// prior to the headers being written. If the set of trailers is fixed // prior to the headers being written. If the set of trailers is fixed
// or known before the header is written, the normal Go trailers mechanism // or known before the header is written, the normal Go trailers mechanism
// is preferred: // is preferred:
// https://golang.org/pkg/net/http/#ResponseWriter //
// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers // https://golang.org/pkg/net/http/#ResponseWriter
// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
const TrailerPrefix = "Trailer:" const TrailerPrefix = "Trailer:"
// promoteUndeclaredTrailers permits http.Handlers to set trailers // promoteUndeclaredTrailers permits http.Handlers to set trailers
@@ -2643,8 +2703,7 @@ func checkWriteHeaderCode(code int) {
// Issue 22880: require valid WriteHeader status codes. // Issue 22880: require valid WriteHeader status codes.
// For now we only enforce that it's three digits. // For now we only enforce that it's three digits.
// In the future we might block things over 599 (600 and above aren't defined // In the future we might block things over 599 (600 and above aren't defined
// at http://httpwg.org/specs/rfc7231.html#status.codes) // at http://httpwg.org/specs/rfc7231.html#status.codes).
// and we might block under 200 (once we have more mature 1xx support).
// But for now any three digits. // But for now any three digits.
// //
// We used to send "HTTP/1.1 000 0" on the wire in responses but there's // We used to send "HTTP/1.1 000 0" on the wire in responses but there's
@@ -2665,13 +2724,41 @@ func (w *responseWriter) WriteHeader(code int) {
} }
func (rws *responseWriterState) writeHeader(code int) { func (rws *responseWriterState) writeHeader(code int) {
if !rws.wroteHeader { if rws.wroteHeader {
checkWriteHeaderCode(code) return
rws.wroteHeader = true }
rws.status = code
if len(rws.handlerHeader) > 0 { checkWriteHeaderCode(code)
rws.snapHeader = cloneHeader(rws.handlerHeader)
// Handle informational headers
if code >= 100 && code <= 199 {
// Per RFC 8297 we must not clear the current header map
h := rws.handlerHeader
_, cl := h["Content-Length"]
_, te := h["Transfer-Encoding"]
if cl || te {
h = h.Clone()
h.Del("Content-Length")
h.Del("Transfer-Encoding")
} }
if rws.conn.writeHeaders(rws.stream, &writeResHeaders{
streamID: rws.stream.id,
httpResCode: code,
h: h,
endStream: rws.handlerDone && !rws.hasTrailers(),
}) != nil {
rws.dirty = true
}
return
}
rws.wroteHeader = true
rws.status = code
if len(rws.handlerHeader) > 0 {
rws.snapHeader = cloneHeader(rws.handlerHeader)
} }
} }

View File

@@ -16,7 +16,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"log" "log"
"math" "math"
mathrand "math/rand" mathrand "math/rand"
@@ -501,12 +500,14 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
if req, err = shouldRetryRequest(req, err); err == nil { if req, err = shouldRetryRequest(req, err); err == nil {
// After the first retry, do exponential backoff with 10% jitter. // After the first retry, do exponential backoff with 10% jitter.
if retry == 0 { if retry == 0 {
t.vlogf("RoundTrip retrying after failure: %v", err)
continue continue
} }
backoff := float64(uint(1) << (uint(retry) - 1)) backoff := float64(uint(1) << (uint(retry) - 1))
backoff += backoff * (0.1 * mathrand.Float64()) backoff += backoff * (0.1 * mathrand.Float64())
select { select {
case <-time.After(time.Second * time.Duration(backoff)): case <-time.After(time.Second * time.Duration(backoff)):
t.vlogf("RoundTrip retrying after failure: %v", err)
continue continue
case <-req.Context().Done(): case <-req.Context().Done():
err = req.Context().Err() err = req.Context().Err()
@@ -732,10 +733,13 @@ func (cc *ClientConn) healthCheck() {
// trigger the healthCheck again if there is no frame received. // trigger the healthCheck again if there is no frame received.
ctx, cancel := context.WithTimeout(context.Background(), pingTimeout) ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
defer cancel() defer cancel()
cc.vlogf("http2: Transport sending health check")
err := cc.Ping(ctx) err := cc.Ping(ctx)
if err != nil { if err != nil {
cc.vlogf("http2: Transport health check failure: %v", err)
cc.closeForLostPing() cc.closeForLostPing()
return } else {
cc.vlogf("http2: Transport health check success")
} }
} }
@@ -1765,7 +1769,8 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
} }
for _, v := range vv { for _, v := range vv {
if !httpguts.ValidHeaderFieldValue(v) { if !httpguts.ValidHeaderFieldValue(v) {
return nil, fmt.Errorf("invalid HTTP header value %q for header %q", v, k) // Don't include the value in the error, because it may be sensitive.
return nil, fmt.Errorf("invalid HTTP header value for header %q", k)
} }
} }
} }
@@ -2898,7 +2903,12 @@ func (t *Transport) logf(format string, args ...interface{}) {
log.Printf(format, args...) log.Printf(format, args...)
} }
var noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil)) var noBody io.ReadCloser = noBodyReader{}
type noBodyReader struct{}
func (noBodyReader) Close() error { return nil }
func (noBodyReader) Read([]byte) (int, error) { return 0, io.EOF }
type missingBody struct{} type missingBody struct{}

View File

@@ -383,16 +383,15 @@ func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority Priorit
func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) { func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
var n *priorityNode var n *priorityNode
if id := wr.StreamID(); id == 0 { if wr.isControl() {
n = &ws.root n = &ws.root
} else { } else {
id := wr.StreamID()
n = ws.nodes[id] n = ws.nodes[id]
if n == nil { if n == nil {
// id is an idle or closed stream. wr should not be a HEADERS or // id is an idle or closed stream. wr should not be a HEADERS or
// DATA frame. However, wr can be a RST_STREAM. In this case, we // DATA frame. In other case, we push wr onto the root, rather
// push wr onto the root, rather than creating a new priorityNode, // than creating a new priorityNode.
// since RST_STREAM is tiny and the stream's priority is unknown
// anyway. See issue #17919.
if wr.DataSize() > 0 { if wr.DataSize() > 0 {
panic("add DATA on non-open stream") panic("add DATA on non-open stream")
} }

View File

@@ -17,23 +17,23 @@ package idna
// //
// The per-rune values have the following format: // The per-rune values have the following format:
// //
// if mapped { // if mapped {
// if inlinedXOR { // if inlinedXOR {
// 15..13 inline XOR marker // 15..13 inline XOR marker
// 12..11 unused // 12..11 unused
// 10..3 inline XOR mask // 10..3 inline XOR mask
// } else { // } else {
// 15..3 index into xor or mapping table // 15..3 index into xor or mapping table
// } // }
// } else { // } else {
// 15..14 unused // 15..14 unused
// 13 mayNeedNorm // 13 mayNeedNorm
// 12..11 attributes // 12..11 attributes
// 10..8 joining type // 10..8 joining type
// 7..3 category type // 7..3 category type
// } // }
// 2 use xor pattern // 2 use xor pattern
// 1..0 mapped category // 1..0 mapped category
// //
// See the definitions below for a more detailed description of the various // See the definitions below for a more detailed description of the various
// bits. // bits.

3
vendor/golang.org/x/sys/AUTHORS generated vendored
View File

@@ -1,3 +0,0 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at http://tip.golang.org/AUTHORS.

View File

@@ -1,3 +0,0 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at http://tip.golang.org/CONTRIBUTORS.

View File

@@ -297,6 +297,10 @@ struct ltchars {
#define SOL_NETLINK 270 #define SOL_NETLINK 270
#endif #endif
#ifndef SOL_SMC
#define SOL_SMC 286
#endif
#ifdef SOL_BLUETOOTH #ifdef SOL_BLUETOOTH
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h // SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
// but it is already in bluetooth_linux.go // but it is already in bluetooth_linux.go

View File

@@ -2940,6 +2940,7 @@ const (
SOL_RAW = 0xff SOL_RAW = 0xff
SOL_RDS = 0x114 SOL_RDS = 0x114
SOL_RXRPC = 0x110 SOL_RXRPC = 0x110
SOL_SMC = 0x11e
SOL_TCP = 0x6 SOL_TCP = 0x6
SOL_TIPC = 0x10f SOL_TIPC = 0x10f
SOL_TLS = 0x11a SOL_TLS = 0x11a

View File

@@ -53,9 +53,8 @@ How to get your contributions merged smoothly and quickly.
- **All tests need to be passing** before your change can be merged. We - **All tests need to be passing** before your change can be merged. We
recommend you **run tests locally** before creating your PR to catch breakages recommend you **run tests locally** before creating your PR to catch breakages
early on. early on.
- `make all` to test everything, OR - `VET_SKIP_PROTO=1 ./vet.sh` to catch vet errors
- `make vet` to catch vet errors - `go test -cpu 1,4 -timeout 7m ./...` to run the tests
- `make test` to run the tests - `go test -race -cpu 1,4 -timeout 7m ./...` to run tests in race mode
- `make testrace` to run tests in race mode
- Exceptions to the rules can be made if there's a compelling reason for doing so. - Exceptions to the rules can be made if there's a compelling reason for doing so.

View File

@@ -8,17 +8,18 @@ See [CONTRIBUTING.md](https://github.com/grpc/grpc-community/blob/master/CONTRIB
for general contribution guidelines. for general contribution guidelines.
## Maintainers (in alphabetical order) ## Maintainers (in alphabetical order)
- [canguler](https://github.com/canguler), Google LLC
- [cesarghali](https://github.com/cesarghali), Google LLC - [cesarghali](https://github.com/cesarghali), Google LLC
- [dfawley](https://github.com/dfawley), Google LLC - [dfawley](https://github.com/dfawley), Google LLC
- [easwars](https://github.com/easwars), Google LLC - [easwars](https://github.com/easwars), Google LLC
- [jadekler](https://github.com/jadekler), Google LLC
- [menghanl](https://github.com/menghanl), Google LLC - [menghanl](https://github.com/menghanl), Google LLC
- [srini100](https://github.com/srini100), Google LLC - [srini100](https://github.com/srini100), Google LLC
## Emeritus Maintainers (in alphabetical order) ## Emeritus Maintainers (in alphabetical order)
- [adelez](https://github.com/adelez), Google LLC - [adelez](https://github.com/adelez), Google LLC
- [canguler](https://github.com/canguler), Google LLC
- [iamqizhao](https://github.com/iamqizhao), Google LLC - [iamqizhao](https://github.com/iamqizhao), Google LLC
- [jadekler](https://github.com/jadekler), Google LLC
- [jtattermusch](https://github.com/jtattermusch), Google LLC - [jtattermusch](https://github.com/jtattermusch), Google LLC
- [lyuxuan](https://github.com/lyuxuan), Google LLC - [lyuxuan](https://github.com/lyuxuan), Google LLC
- [makmukhi](https://github.com/makmukhi), Google LLC - [makmukhi](https://github.com/makmukhi), Google LLC

View File

@@ -41,8 +41,6 @@ vetdeps:
clean \ clean \
proto \ proto \
test \ test \
testappengine \
testappenginedeps \
testrace \ testrace \
vet \ vet \
vetdeps vetdeps

13
vendor/google.golang.org/grpc/NOTICE.txt generated vendored Normal file
View File

@@ -0,0 +1,13 @@
Copyright 2014 gRPC authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -25,55 +25,77 @@
// later release. // later release.
package attributes package attributes
import "fmt"
// Attributes is an immutable struct for storing and retrieving generic // Attributes is an immutable struct for storing and retrieving generic
// key/value pairs. Keys must be hashable, and users should define their own // key/value pairs. Keys must be hashable, and users should define their own
// types for keys. // types for keys. Values should not be modified after they are added to an
// Attributes or if they were received from one. If values implement 'Equal(o
// interface{}) bool', it will be called by (*Attributes).Equal to determine
// whether two values with the same key should be considered equal.
type Attributes struct { type Attributes struct {
m map[interface{}]interface{} m map[interface{}]interface{}
} }
// New returns a new Attributes containing all key/value pairs in kvs. If the // New returns a new Attributes containing the key/value pair.
// same key appears multiple times, the last value overwrites all previous func New(key, value interface{}) *Attributes {
// values for that key. Panics if len(kvs) is not even. return &Attributes{m: map[interface{}]interface{}{key: value}}
func New(kvs ...interface{}) *Attributes {
if len(kvs)%2 != 0 {
panic(fmt.Sprintf("attributes.New called with unexpected input: len(kvs) = %v", len(kvs)))
}
a := &Attributes{m: make(map[interface{}]interface{}, len(kvs)/2)}
for i := 0; i < len(kvs)/2; i++ {
a.m[kvs[i*2]] = kvs[i*2+1]
}
return a
} }
// WithValues returns a new Attributes containing all key/value pairs in a and // WithValue returns a new Attributes containing the previous keys and values
// kvs. Panics if len(kvs) is not even. If the same key appears multiple // and the new key/value pair. If the same key appears multiple times, the
// times, the last value overwrites all previous values for that key. To // last value overwrites all previous values for that key. To remove an
// remove an existing key, use a nil value. // existing key, use a nil value. value should not be modified later.
func (a *Attributes) WithValues(kvs ...interface{}) *Attributes { func (a *Attributes) WithValue(key, value interface{}) *Attributes {
if a == nil { if a == nil {
return New(kvs...) return New(key, value)
} }
if len(kvs)%2 != 0 { n := &Attributes{m: make(map[interface{}]interface{}, len(a.m)+1)}
panic(fmt.Sprintf("attributes.New called with unexpected input: len(kvs) = %v", len(kvs)))
}
n := &Attributes{m: make(map[interface{}]interface{}, len(a.m)+len(kvs)/2)}
for k, v := range a.m { for k, v := range a.m {
n.m[k] = v n.m[k] = v
} }
for i := 0; i < len(kvs)/2; i++ { n.m[key] = value
n.m[kvs[i*2]] = kvs[i*2+1]
}
return n return n
} }
// Value returns the value associated with these attributes for key, or nil if // Value returns the value associated with these attributes for key, or nil if
// no value is associated with key. // no value is associated with key. The returned value should not be modified.
func (a *Attributes) Value(key interface{}) interface{} { func (a *Attributes) Value(key interface{}) interface{} {
if a == nil { if a == nil {
return nil return nil
} }
return a.m[key] return a.m[key]
} }
// Equal returns whether a and o are equivalent. If 'Equal(o interface{})
// bool' is implemented for a value in the attributes, it is called to
// determine if the value matches the one stored in the other attributes. If
// Equal is not implemented, standard equality is used to determine if the two
// values are equal. Note that some types (e.g. maps) aren't comparable by
// default, so they must be wrapped in a struct, or in an alias type, with Equal
// defined.
func (a *Attributes) Equal(o *Attributes) bool {
if a == nil && o == nil {
return true
}
if a == nil || o == nil {
return false
}
if len(a.m) != len(o.m) {
return false
}
for k, v := range a.m {
ov, ok := o.m[k]
if !ok {
// o missing element of a
return false
}
if eq, ok := v.(interface{ Equal(o interface{}) bool }); ok {
if !eq.Equal(ov) {
return false
}
} else if v != ov {
// Fallback to a standard equality check if Value is unimplemented.
return false
}
}
return true
}

View File

@@ -27,6 +27,7 @@ import (
"net" "net"
"strings" "strings"
"google.golang.org/grpc/channelz"
"google.golang.org/grpc/connectivity" "google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal" "google.golang.org/grpc/internal"
@@ -75,24 +76,26 @@ func Get(name string) Builder {
return nil return nil
} }
// SubConn represents a gRPC sub connection. // A SubConn represents a single connection to a gRPC backend service.
// Each sub connection contains a list of addresses. gRPC will
// try to connect to them (in sequence), and stop trying the
// remainder once one connection is successful.
// //
// The reconnect backoff will be applied on the list, not a single address. // Each SubConn contains a list of addresses.
// For example, try_on_all_addresses -> backoff -> try_on_all_addresses.
// //
// All SubConns start in IDLE, and will not try to connect. To trigger // All SubConns start in IDLE, and will not try to connect. To trigger the
// the connecting, Balancers must call Connect. // connecting, Balancers must call Connect. If a connection re-enters IDLE,
// When the connection encounters an error, it will reconnect immediately. // Balancers must call Connect again to trigger a new connection attempt.
// When the connection becomes IDLE, it will not reconnect unless Connect is
// called.
// //
// This interface is to be implemented by gRPC. Users should not need a // gRPC will try to connect to the addresses in sequence, and stop trying the
// brand new implementation of this interface. For the situations like // remainder once the first connection is successful. If an attempt to connect
// testing, the new implementation should embed this interface. This allows // to all addresses encounters an error, the SubConn will enter
// gRPC to add new methods to this interface. // TRANSIENT_FAILURE for a backoff period, and then transition to IDLE.
//
// Once established, if a connection is lost, the SubConn will transition
// directly to IDLE.
//
// This interface is to be implemented by gRPC. Users should not need their own
// implementation of this interface. For situations like testing, any
// implementations should embed this interface. This allows gRPC to add new
// methods to this interface.
type SubConn interface { type SubConn interface {
// UpdateAddresses updates the addresses used in this SubConn. // UpdateAddresses updates the addresses used in this SubConn.
// gRPC checks if currently-connected address is still in the new list. // gRPC checks if currently-connected address is still in the new list.
@@ -172,25 +175,32 @@ type ClientConn interface {
// BuildOptions contains additional information for Build. // BuildOptions contains additional information for Build.
type BuildOptions struct { type BuildOptions struct {
// DialCreds is the transport credential the Balancer implementation can // DialCreds is the transport credentials to use when communicating with a
// use to dial to a remote load balancer server. The Balancer implementations // remote load balancer server. Balancer implementations which do not
// can ignore this if it does not need to talk to another party securely. // communicate with a remote load balancer server can ignore this field.
DialCreds credentials.TransportCredentials DialCreds credentials.TransportCredentials
// CredsBundle is the credentials bundle that the Balancer can use. // CredsBundle is the credentials bundle to use when communicating with a
// remote load balancer server. Balancer implementations which do not
// communicate with a remote load balancer server can ignore this field.
CredsBundle credentials.Bundle CredsBundle credentials.Bundle
// Dialer is the custom dialer the Balancer implementation can use to dial // Dialer is the custom dialer to use when communicating with a remote load
// to a remote load balancer server. The Balancer implementations // balancer server. Balancer implementations which do not communicate with a
// can ignore this if it doesn't need to talk to remote balancer. // remote load balancer server can ignore this field.
Dialer func(context.Context, string) (net.Conn, error) Dialer func(context.Context, string) (net.Conn, error)
// ChannelzParentID is the entity parent's channelz unique identification number. // Authority is the server name to use as part of the authentication
ChannelzParentID int64 // handshake when communicating with a remote load balancer server. Balancer
// implementations which do not communicate with a remote load balancer
// server can ignore this field.
Authority string
// ChannelzParentID is the parent ClientConn's channelz ID.
ChannelzParentID *channelz.Identifier
// CustomUserAgent is the custom user agent set on the parent ClientConn. // CustomUserAgent is the custom user agent set on the parent ClientConn.
// The balancer should set the same custom user agent if it creates a // The balancer should set the same custom user agent if it creates a
// ClientConn. // ClientConn.
CustomUserAgent string CustomUserAgent string
// Target contains the parsed address info of the dial target. It is the same resolver.Target as // Target contains the parsed address info of the dial target. It is the
// passed to the resolver. // same resolver.Target as passed to the resolver. See the documentation for
// See the documentation for the resolver.Target type for details about what it contains. // the resolver.Target type for details about what it contains.
Target resolver.Target Target resolver.Target
} }
@@ -326,6 +336,20 @@ type Balancer interface {
Close() Close()
} }
// ExitIdler is an optional interface for balancers to implement. If
// implemented, ExitIdle will be called when ClientConn.Connect is called, if
// the ClientConn is idle. If unimplemented, ClientConn.Connect will cause
// all SubConns to connect.
//
// Notice: it will be required for all balancers to implement this in a future
// release.
type ExitIdler interface {
// ExitIdle instructs the LB policy to reconnect to backends / exit the
// IDLE state, if appropriate and possible. Note that SubConns that enter
// the IDLE state will not reconnect until SubConn.Connect is called.
ExitIdle()
}
// SubConnState describes the state of a SubConn. // SubConnState describes the state of a SubConn.
type SubConnState struct { type SubConnState struct {
// ConnectivityState is the connectivity state of the SubConn. // ConnectivityState is the connectivity state of the SubConn.
@@ -353,8 +377,10 @@ var ErrBadResolverState = errors.New("bad resolver state")
// //
// It's not thread safe. // It's not thread safe.
type ConnectivityStateEvaluator struct { type ConnectivityStateEvaluator struct {
numReady uint64 // Number of addrConns in ready state. numReady uint64 // Number of addrConns in ready state.
numConnecting uint64 // Number of addrConns in connecting state. numConnecting uint64 // Number of addrConns in connecting state.
numTransientFailure uint64 // Number of addrConns in transient failure state.
numIdle uint64 // Number of addrConns in idle state.
} }
// RecordTransition records state change happening in subConn and based on that // RecordTransition records state change happening in subConn and based on that
@@ -362,9 +388,11 @@ type ConnectivityStateEvaluator struct {
// //
// - If at least one SubConn in Ready, the aggregated state is Ready; // - If at least one SubConn in Ready, the aggregated state is Ready;
// - Else if at least one SubConn in Connecting, the aggregated state is Connecting; // - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
// - Else the aggregated state is TransientFailure. // - Else if at least one SubConn is TransientFailure, the aggregated state is Transient Failure;
// - Else if at least one SubConn is Idle, the aggregated state is Idle;
// - Else there are no subconns and the aggregated state is Transient Failure
// //
// Idle and Shutdown are not considered. // Shutdown is not considered.
func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State { func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State {
// Update counters. // Update counters.
for idx, state := range []connectivity.State{oldState, newState} { for idx, state := range []connectivity.State{oldState, newState} {
@@ -374,6 +402,10 @@ func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState conne
cse.numReady += updateVal cse.numReady += updateVal
case connectivity.Connecting: case connectivity.Connecting:
cse.numConnecting += updateVal cse.numConnecting += updateVal
case connectivity.TransientFailure:
cse.numTransientFailure += updateVal
case connectivity.Idle:
cse.numIdle += updateVal
} }
} }
@@ -384,5 +416,11 @@ func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState conne
if cse.numConnecting > 0 { if cse.numConnecting > 0 {
return connectivity.Connecting return connectivity.Connecting
} }
if cse.numTransientFailure > 0 {
return connectivity.TransientFailure
}
if cse.numIdle > 0 {
return connectivity.Idle
}
return connectivity.TransientFailure return connectivity.TransientFailure
} }

View File

@@ -22,7 +22,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"google.golang.org/grpc/attributes"
"google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer"
"google.golang.org/grpc/connectivity" "google.golang.org/grpc/connectivity"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
@@ -42,7 +41,7 @@ func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions)
cc: cc, cc: cc,
pickerBuilder: bb.pickerBuilder, pickerBuilder: bb.pickerBuilder,
subConns: make(map[resolver.Address]subConnInfo), subConns: resolver.NewAddressMap(),
scStates: make(map[balancer.SubConn]connectivity.State), scStates: make(map[balancer.SubConn]connectivity.State),
csEvltr: &balancer.ConnectivityStateEvaluator{}, csEvltr: &balancer.ConnectivityStateEvaluator{},
config: bb.config, config: bb.config,
@@ -58,11 +57,6 @@ func (bb *baseBuilder) Name() string {
return bb.name return bb.name
} }
type subConnInfo struct {
subConn balancer.SubConn
attrs *attributes.Attributes
}
type baseBalancer struct { type baseBalancer struct {
cc balancer.ClientConn cc balancer.ClientConn
pickerBuilder PickerBuilder pickerBuilder PickerBuilder
@@ -70,7 +64,7 @@ type baseBalancer struct {
csEvltr *balancer.ConnectivityStateEvaluator csEvltr *balancer.ConnectivityStateEvaluator
state connectivity.State state connectivity.State
subConns map[resolver.Address]subConnInfo // `attributes` is stripped from the keys of this map (the addresses) subConns *resolver.AddressMap
scStates map[balancer.SubConn]connectivity.State scStates map[balancer.SubConn]connectivity.State
picker balancer.Picker picker balancer.Picker
config Config config Config
@@ -81,7 +75,7 @@ type baseBalancer struct {
func (b *baseBalancer) ResolverError(err error) { func (b *baseBalancer) ResolverError(err error) {
b.resolverErr = err b.resolverErr = err
if len(b.subConns) == 0 { if b.subConns.Len() == 0 {
b.state = connectivity.TransientFailure b.state = connectivity.TransientFailure
} }
@@ -105,52 +99,29 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
// Successful resolution; clear resolver error and ensure we return nil. // Successful resolution; clear resolver error and ensure we return nil.
b.resolverErr = nil b.resolverErr = nil
// addrsSet is the set converted from addrs, it's used for quick lookup of an address. // addrsSet is the set converted from addrs, it's used for quick lookup of an address.
addrsSet := make(map[resolver.Address]struct{}) addrsSet := resolver.NewAddressMap()
for _, a := range s.ResolverState.Addresses { for _, a := range s.ResolverState.Addresses {
// Strip attributes from addresses before using them as map keys. So addrsSet.Set(a, nil)
// that when two addresses only differ in attributes pointers (but with if _, ok := b.subConns.Get(a); !ok {
// the same attribute content), they are considered the same address.
//
// Note that this doesn't handle the case where the attribute content is
// different. So if users want to set different attributes to create
// duplicate connections to the same backend, it doesn't work. This is
// fine for now, because duplicate is done by setting Metadata today.
//
// TODO: read attributes to handle duplicate connections.
aNoAttrs := a
aNoAttrs.Attributes = nil
addrsSet[aNoAttrs] = struct{}{}
if scInfo, ok := b.subConns[aNoAttrs]; !ok {
// a is a new address (not existing in b.subConns). // a is a new address (not existing in b.subConns).
//
// When creating SubConn, the original address with attributes is
// passed through. So that connection configurations in attributes
// (like creds) will be used.
sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck}) sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
if err != nil { if err != nil {
logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err) logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
continue continue
} }
b.subConns[aNoAttrs] = subConnInfo{subConn: sc, attrs: a.Attributes} b.subConns.Set(a, sc)
b.scStates[sc] = connectivity.Idle b.scStates[sc] = connectivity.Idle
b.csEvltr.RecordTransition(connectivity.Shutdown, connectivity.Idle)
sc.Connect() sc.Connect()
} else {
// Always update the subconn's address in case the attributes
// changed.
//
// The SubConn does a reflect.DeepEqual of the new and old
// addresses. So this is a noop if the current address is the same
// as the old one (including attributes).
scInfo.attrs = a.Attributes
b.subConns[aNoAttrs] = scInfo
b.cc.UpdateAddresses(scInfo.subConn, []resolver.Address{a})
} }
} }
for a, scInfo := range b.subConns { for _, a := range b.subConns.Keys() {
sci, _ := b.subConns.Get(a)
sc := sci.(balancer.SubConn)
// a was removed by resolver. // a was removed by resolver.
if _, ok := addrsSet[a]; !ok { if _, ok := addrsSet.Get(a); !ok {
b.cc.RemoveSubConn(scInfo.subConn) b.cc.RemoveSubConn(sc)
delete(b.subConns, a) b.subConns.Delete(a)
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown. // Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
// The entry will be deleted in UpdateSubConnState. // The entry will be deleted in UpdateSubConnState.
} }
@@ -192,10 +163,11 @@ func (b *baseBalancer) regeneratePicker() {
readySCs := make(map[balancer.SubConn]SubConnInfo) readySCs := make(map[balancer.SubConn]SubConnInfo)
// Filter out all ready SCs from full subConn map. // Filter out all ready SCs from full subConn map.
for addr, scInfo := range b.subConns { for _, addr := range b.subConns.Keys() {
if st, ok := b.scStates[scInfo.subConn]; ok && st == connectivity.Ready { sci, _ := b.subConns.Get(addr)
addr.Attributes = scInfo.attrs sc := sci.(balancer.SubConn)
readySCs[scInfo.subConn] = SubConnInfo{Address: addr} if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
readySCs[sc] = SubConnInfo{Address: addr}
} }
} }
b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs}) b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})
@@ -213,10 +185,14 @@ func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.Su
} }
return return
} }
if oldS == connectivity.TransientFailure && s == connectivity.Connecting { if oldS == connectivity.TransientFailure &&
// Once a subconn enters TRANSIENT_FAILURE, ignore subsequent (s == connectivity.Connecting || s == connectivity.Idle) {
// Once a subconn enters TRANSIENT_FAILURE, ignore subsequent IDLE or
// CONNECTING transitions to prevent the aggregated state from being // CONNECTING transitions to prevent the aggregated state from being
// always CONNECTING when many backends exist but are all down. // always CONNECTING when many backends exist but are all down.
if s == connectivity.Idle {
sc.Connect()
}
return return
} }
b.scStates[sc] = s b.scStates[sc] = s
@@ -242,7 +218,6 @@ func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.Su
b.state == connectivity.TransientFailure { b.state == connectivity.TransientFailure {
b.regeneratePicker() b.regeneratePicker()
} }
b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker}) b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker})
} }
@@ -251,6 +226,11 @@ func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.Su
func (b *baseBalancer) Close() { func (b *baseBalancer) Close() {
} }
// ExitIdle is a nop because the base balancer attempts to stay connected to
// all SubConns at all times.
func (b *baseBalancer) ExitIdle() {
}
// NewErrPicker returns a Picker that always returns err on Pick(). // NewErrPicker returns a Picker that always returns err on Pick().
func NewErrPicker(err error) balancer.Picker { func NewErrPicker(err error) balancer.Picker {
return &errPicker{err: err} return &errPicker{err: err}

View File

@@ -39,7 +39,7 @@ type State struct {
// Set returns a copy of the provided state with attributes containing s. s's // Set returns a copy of the provided state with attributes containing s. s's
// data should not be mutated after calling Set. // data should not be mutated after calling Set.
func Set(state resolver.State, s *State) resolver.State { func Set(state resolver.State, s *State) resolver.State {
state.Attributes = state.Attributes.WithValues(key, s) state.Attributes = state.Attributes.WithValue(key, s)
return state return state
} }

View File

@@ -47,11 +47,11 @@ func init() {
type rrPickerBuilder struct{} type rrPickerBuilder struct{}
func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker { func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker {
logger.Infof("roundrobinPicker: newPicker called with info: %v", info) logger.Infof("roundrobinPicker: Build called with info: %v", info)
if len(info.ReadySCs) == 0 { if len(info.ReadySCs) == 0 {
return base.NewErrPicker(balancer.ErrNoSubConnAvailable) return base.NewErrPicker(balancer.ErrNoSubConnAvailable)
} }
var scs []balancer.SubConn scs := make([]balancer.SubConn, 0, len(info.ReadySCs))
for sc := range info.ReadySCs { for sc := range info.ReadySCs {
scs = append(scs, sc) scs = append(scs, sc)
} }

View File

@@ -20,105 +20,178 @@ package grpc
import ( import (
"fmt" "fmt"
"strings"
"sync" "sync"
"google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer"
"google.golang.org/grpc/connectivity" "google.golang.org/grpc/connectivity"
"google.golang.org/grpc/internal/balancer/gracefulswitch"
"google.golang.org/grpc/internal/buffer" "google.golang.org/grpc/internal/buffer"
"google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/channelz"
"google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpcsync"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
) )
// scStateUpdate contains the subConn and the new state it changed to. // ccBalancerWrapper sits between the ClientConn and the Balancer.
//
// ccBalancerWrapper implements methods corresponding to the ones on the
// balancer.Balancer interface. The ClientConn is free to call these methods
// concurrently and the ccBalancerWrapper ensures that calls from the ClientConn
// to the Balancer happen synchronously and in order.
//
// ccBalancerWrapper also implements the balancer.ClientConn interface and is
// passed to the Balancer implementations. It invokes unexported methods on the
// ClientConn to handle these calls from the Balancer.
//
// It uses the gracefulswitch.Balancer internally to ensure that balancer
// switches happen in a graceful manner.
type ccBalancerWrapper struct {
cc *ClientConn
// Since these fields are accessed only from handleXxx() methods which are
// synchronized by the watcher goroutine, we do not need a mutex to protect
// these fields.
balancer *gracefulswitch.Balancer
curBalancerName string
updateCh *buffer.Unbounded // Updates written on this channel are processed by watcher().
resultCh *buffer.Unbounded // Results of calls to UpdateClientConnState() are pushed here.
closed *grpcsync.Event // Indicates if close has been called.
done *grpcsync.Event // Indicates if close has completed its work.
}
// newCCBalancerWrapper creates a new balancer wrapper. The underlying balancer
// is not created until the switchTo() method is invoked.
func newCCBalancerWrapper(cc *ClientConn, bopts balancer.BuildOptions) *ccBalancerWrapper {
ccb := &ccBalancerWrapper{
cc: cc,
updateCh: buffer.NewUnbounded(),
resultCh: buffer.NewUnbounded(),
closed: grpcsync.NewEvent(),
done: grpcsync.NewEvent(),
}
go ccb.watcher()
ccb.balancer = gracefulswitch.NewBalancer(ccb, bopts)
return ccb
}
// The following xxxUpdate structs wrap the arguments received as part of the
// corresponding update. The watcher goroutine uses the 'type' of the update to
// invoke the appropriate handler routine to handle the update.
type ccStateUpdate struct {
ccs *balancer.ClientConnState
}
type scStateUpdate struct { type scStateUpdate struct {
sc balancer.SubConn sc balancer.SubConn
state connectivity.State state connectivity.State
err error err error
} }
// ccBalancerWrapper is a wrapper on top of cc for balancers. type exitIdleUpdate struct{}
// It implements balancer.ClientConn interface.
type ccBalancerWrapper struct {
cc *ClientConn
balancerMu sync.Mutex // synchronizes calls to the balancer
balancer balancer.Balancer
updateCh *buffer.Unbounded
closed *grpcsync.Event
done *grpcsync.Event
mu sync.Mutex type resolverErrorUpdate struct {
subConns map[*acBalancerWrapper]struct{} err error
} }
func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper { type switchToUpdate struct {
ccb := &ccBalancerWrapper{ name string
cc: cc,
updateCh: buffer.NewUnbounded(),
closed: grpcsync.NewEvent(),
done: grpcsync.NewEvent(),
subConns: make(map[*acBalancerWrapper]struct{}),
}
go ccb.watcher()
ccb.balancer = b.Build(ccb, bopts)
return ccb
} }
// watcher balancer functions sequentially, so the balancer can be implemented type subConnUpdate struct {
// lock-free. acbw *acBalancerWrapper
}
// watcher is a long-running goroutine which reads updates from a channel and
// invokes corresponding methods on the underlying balancer. It ensures that
// these methods are invoked in a synchronous fashion. It also ensures that
// these methods are invoked in the order in which the updates were received.
func (ccb *ccBalancerWrapper) watcher() { func (ccb *ccBalancerWrapper) watcher() {
for { for {
select { select {
case t := <-ccb.updateCh.Get(): case u := <-ccb.updateCh.Get():
ccb.updateCh.Load() ccb.updateCh.Load()
if ccb.closed.HasFired() { if ccb.closed.HasFired() {
break break
} }
switch u := t.(type) { switch update := u.(type) {
case *ccStateUpdate:
ccb.handleClientConnStateChange(update.ccs)
case *scStateUpdate: case *scStateUpdate:
ccb.balancerMu.Lock() ccb.handleSubConnStateChange(update)
ccb.balancer.UpdateSubConnState(u.sc, balancer.SubConnState{ConnectivityState: u.state, ConnectionError: u.err}) case *exitIdleUpdate:
ccb.balancerMu.Unlock() ccb.handleExitIdle()
case *acBalancerWrapper: case *resolverErrorUpdate:
ccb.mu.Lock() ccb.handleResolverError(update.err)
if ccb.subConns != nil { case *switchToUpdate:
delete(ccb.subConns, u) ccb.handleSwitchTo(update.name)
ccb.cc.removeAddrConn(u.getAddrConn(), errConnDrain) case *subConnUpdate:
} ccb.handleRemoveSubConn(update.acbw)
ccb.mu.Unlock()
default: default:
logger.Errorf("ccBalancerWrapper.watcher: unknown update %+v, type %T", t, t) logger.Errorf("ccBalancerWrapper.watcher: unknown update %+v, type %T", update, update)
} }
case <-ccb.closed.Done(): case <-ccb.closed.Done():
} }
if ccb.closed.HasFired() { if ccb.closed.HasFired() {
ccb.balancerMu.Lock() ccb.handleClose()
ccb.balancer.Close()
ccb.balancerMu.Unlock()
ccb.mu.Lock()
scs := ccb.subConns
ccb.subConns = nil
ccb.mu.Unlock()
ccb.UpdateState(balancer.State{ConnectivityState: connectivity.Connecting, Picker: nil})
ccb.done.Fire()
// Fire done before removing the addr conns. We can safely unblock
// ccb.close and allow the removeAddrConns to happen
// asynchronously.
for acbw := range scs {
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
}
return return
} }
} }
} }
func (ccb *ccBalancerWrapper) close() { // updateClientConnState is invoked by grpc to push a ClientConnState update to
ccb.closed.Fire() // the underlying balancer.
<-ccb.done.Done() //
// Unlike other methods invoked by grpc to push updates to the underlying
// balancer, this method cannot simply push the update onto the update channel
// and return. It needs to return the error returned by the underlying balancer
// back to grpc which propagates that to the resolver.
func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error {
ccb.updateCh.Put(&ccStateUpdate{ccs: ccs})
var res interface{}
select {
case res = <-ccb.resultCh.Get():
ccb.resultCh.Load()
case <-ccb.closed.Done():
// Return early if the balancer wrapper is closed while we are waiting for
// the underlying balancer to process a ClientConnState update.
return nil
}
// If the returned error is nil, attempting to type assert to error leads to
// panic. So, this needs to handled separately.
if res == nil {
return nil
}
return res.(error)
} }
func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State, err error) { // handleClientConnStateChange handles a ClientConnState update from the update
// channel and invokes the appropriate method on the underlying balancer.
//
// If the addresses specified in the update contain addresses of type "grpclb"
// and the selected LB policy is not "grpclb", these addresses will be filtered
// out and ccs will be modified with the updated address list.
func (ccb *ccBalancerWrapper) handleClientConnStateChange(ccs *balancer.ClientConnState) {
if ccb.curBalancerName != grpclbName {
// Filter any grpclb addresses since we don't have the grpclb balancer.
var addrs []resolver.Address
for _, addr := range ccs.ResolverState.Addresses {
if addr.Type == resolver.GRPCLB {
continue
}
addrs = append(addrs, addr)
}
ccs.ResolverState.Addresses = addrs
}
ccb.resultCh.Put(ccb.balancer.UpdateClientConnState(*ccs))
}
// updateSubConnState is invoked by grpc to push a subConn state update to the
// underlying balancer.
func (ccb *ccBalancerWrapper) updateSubConnState(sc balancer.SubConn, s connectivity.State, err error) {
// When updating addresses for a SubConn, if the address in use is not in // When updating addresses for a SubConn, if the address in use is not in
// the new addresses, the old ac will be tearDown() and a new ac will be // the new addresses, the old ac will be tearDown() and a new ac will be
// created. tearDown() generates a state change with Shutdown state, we // created. tearDown() generates a state change with Shutdown state, we
@@ -136,44 +209,125 @@ func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s co
}) })
} }
func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error { // handleSubConnStateChange handles a SubConnState update from the update
ccb.balancerMu.Lock() // channel and invokes the appropriate method on the underlying balancer.
defer ccb.balancerMu.Unlock() func (ccb *ccBalancerWrapper) handleSubConnStateChange(update *scStateUpdate) {
return ccb.balancer.UpdateClientConnState(*ccs) ccb.balancer.UpdateSubConnState(update.sc, balancer.SubConnState{ConnectivityState: update.state, ConnectionError: update.err})
}
func (ccb *ccBalancerWrapper) exitIdle() {
ccb.updateCh.Put(&exitIdleUpdate{})
}
func (ccb *ccBalancerWrapper) handleExitIdle() {
if ccb.cc.GetState() != connectivity.Idle {
return
}
ccb.balancer.ExitIdle()
} }
func (ccb *ccBalancerWrapper) resolverError(err error) { func (ccb *ccBalancerWrapper) resolverError(err error) {
ccb.balancerMu.Lock() ccb.updateCh.Put(&resolverErrorUpdate{err: err})
}
func (ccb *ccBalancerWrapper) handleResolverError(err error) {
ccb.balancer.ResolverError(err) ccb.balancer.ResolverError(err)
ccb.balancerMu.Unlock() }
// switchTo is invoked by grpc to instruct the balancer wrapper to switch to the
// LB policy identified by name.
//
// ClientConn calls newCCBalancerWrapper() at creation time. Upon receipt of the
// first good update from the name resolver, it determines the LB policy to use
// and invokes the switchTo() method. Upon receipt of every subsequent update
// from the name resolver, it invokes this method.
//
// the ccBalancerWrapper keeps track of the current LB policy name, and skips
// the graceful balancer switching process if the name does not change.
func (ccb *ccBalancerWrapper) switchTo(name string) {
ccb.updateCh.Put(&switchToUpdate{name: name})
}
// handleSwitchTo handles a balancer switch update from the update channel. It
// calls the SwitchTo() method on the gracefulswitch.Balancer with a
// balancer.Builder corresponding to name. If no balancer.Builder is registered
// for the given name, it uses the default LB policy which is "pick_first".
func (ccb *ccBalancerWrapper) handleSwitchTo(name string) {
// TODO: Other languages use case-insensitive balancer registries. We should
// switch as well. See: https://github.com/grpc/grpc-go/issues/5288.
if strings.EqualFold(ccb.curBalancerName, name) {
return
}
// TODO: Ensure that name is a registered LB policy when we get here.
// We currently only validate the `loadBalancingConfig` field. We need to do
// the same for the `loadBalancingPolicy` field and reject the service config
// if the specified policy is not registered.
builder := balancer.Get(name)
if builder == nil {
channelz.Warningf(logger, ccb.cc.channelzID, "Channel switches to new LB policy %q, since the specified LB policy %q was not registered", PickFirstBalancerName, name)
builder = newPickfirstBuilder()
} else {
channelz.Infof(logger, ccb.cc.channelzID, "Channel switches to new LB policy %q", name)
}
if err := ccb.balancer.SwitchTo(builder); err != nil {
channelz.Errorf(logger, ccb.cc.channelzID, "Channel failed to build new LB policy %q: %v", name, err)
return
}
ccb.curBalancerName = builder.Name()
}
// handleRemoveSucConn handles a request from the underlying balancer to remove
// a subConn.
//
// See comments in RemoveSubConn() for more details.
func (ccb *ccBalancerWrapper) handleRemoveSubConn(acbw *acBalancerWrapper) {
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
}
func (ccb *ccBalancerWrapper) close() {
ccb.closed.Fire()
<-ccb.done.Done()
}
func (ccb *ccBalancerWrapper) handleClose() {
ccb.balancer.Close()
ccb.done.Fire()
} }
func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) { func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
if len(addrs) <= 0 { if len(addrs) <= 0 {
return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list") return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
} }
ccb.mu.Lock()
defer ccb.mu.Unlock()
if ccb.subConns == nil {
return nil, fmt.Errorf("grpc: ClientConn balancer wrapper was closed")
}
ac, err := ccb.cc.newAddrConn(addrs, opts) ac, err := ccb.cc.newAddrConn(addrs, opts)
if err != nil { if err != nil {
channelz.Warningf(logger, ccb.cc.channelzID, "acBalancerWrapper: NewSubConn: failed to newAddrConn: %v", err)
return nil, err return nil, err
} }
acbw := &acBalancerWrapper{ac: ac} acbw := &acBalancerWrapper{ac: ac}
acbw.ac.mu.Lock() acbw.ac.mu.Lock()
ac.acbw = acbw ac.acbw = acbw
acbw.ac.mu.Unlock() acbw.ac.mu.Unlock()
ccb.subConns[acbw] = struct{}{}
return acbw, nil return acbw, nil
} }
func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) { func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
// The RemoveSubConn() is handled in the run() goroutine, to avoid deadlock // Before we switched the ccBalancerWrapper to use gracefulswitch.Balancer, it
// during switchBalancer() if the old balancer calls RemoveSubConn() in its // was required to handle the RemoveSubConn() method asynchronously by pushing
// Close(). // the update onto the update channel. This was done to avoid a deadlock as
ccb.updateCh.Put(sc) // switchBalancer() was holding cc.mu when calling Close() on the old
// balancer, which would in turn call RemoveSubConn().
//
// With the use of gracefulswitch.Balancer in ccBalancerWrapper, handling this
// asynchronously is probably not required anymore since the switchTo() method
// handles the balancer switch by pushing the update onto the channel.
// TODO(easwars): Handle this inline.
acbw, ok := sc.(*acBalancerWrapper)
if !ok {
return
}
ccb.updateCh.Put(&subConnUpdate{acbw: acbw})
} }
func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) { func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
@@ -185,11 +339,6 @@ func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resol
} }
func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) { func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
ccb.mu.Lock()
defer ccb.mu.Unlock()
if ccb.subConns == nil {
return
}
// Update picker before updating state. Even though the ordering here does // Update picker before updating state. Even though the ordering here does
// not matter, it can lead to multiple calls of Pick in the common start-up // not matter, it can lead to multiple calls of Pick in the common start-up
// case where we wait for ready and then perform an RPC. If the picker is // case where we wait for ready and then perform an RPC. If the picker is
@@ -239,17 +388,17 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
return return
} }
ac, err := cc.newAddrConn(addrs, opts) newAC, err := cc.newAddrConn(addrs, opts)
if err != nil { if err != nil {
channelz.Warningf(logger, acbw.ac.channelzID, "acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err) channelz.Warningf(logger, acbw.ac.channelzID, "acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
return return
} }
acbw.ac = ac acbw.ac = newAC
ac.mu.Lock() newAC.mu.Lock()
ac.acbw = acbw newAC.acbw = acbw
ac.mu.Unlock() newAC.mu.Unlock()
if acState != connectivity.Idle { if acState != connectivity.Idle {
ac.connect() go newAC.connect()
} }
} }
} }
@@ -257,7 +406,7 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
func (acbw *acBalancerWrapper) Connect() { func (acbw *acBalancerWrapper) Connect() {
acbw.mu.Lock() acbw.mu.Lock()
defer acbw.mu.Unlock() defer acbw.mu.Unlock()
acbw.ac.connect() go acbw.ac.connect()
} }
func (acbw *acBalancerWrapper) getAddrConn() *addrConn { func (acbw *acBalancerWrapper) getAddrConn() *addrConn {

36
vendor/google.golang.org/grpc/channelz/channelz.go generated vendored Normal file
View File

@@ -0,0 +1,36 @@
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package channelz exports internals of the channelz implementation as required
// by other gRPC packages.
//
// The implementation of the channelz spec as defined in
// https://github.com/grpc/proposal/blob/master/A14-channelz.md, is provided by
// the `internal/channelz` package.
//
// Experimental
//
// Notice: All APIs in this package are experimental and may be removed in a
// later release.
package channelz
import "google.golang.org/grpc/internal/channelz"
// Identifier is an opaque identifier which uniquely identifies an entity in the
// channelz database.
type Identifier = channelz.Identifier

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,6 @@
// Package connectivity defines connectivity semantics. // Package connectivity defines connectivity semantics.
// For details, see https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md. // For details, see https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md.
// All APIs in this package are experimental.
package connectivity package connectivity
import ( import (
@@ -45,7 +44,7 @@ func (s State) String() string {
return "SHUTDOWN" return "SHUTDOWN"
default: default:
logger.Errorf("unknown connectivity state: %d", s) logger.Errorf("unknown connectivity state: %d", s)
return "Invalid-State" return "INVALID_STATE"
} }
} }
@@ -61,3 +60,35 @@ const (
// Shutdown indicates the ClientConn has started shutting down. // Shutdown indicates the ClientConn has started shutting down.
Shutdown Shutdown
) )
// ServingMode indicates the current mode of operation of the server.
//
// Only xDS enabled gRPC servers currently report their serving mode.
type ServingMode int
const (
// ServingModeStarting indicates that the server is starting up.
ServingModeStarting ServingMode = iota
// ServingModeServing indicates that the server contains all required
// configuration and is serving RPCs.
ServingModeServing
// ServingModeNotServing indicates that the server is not accepting new
// connections. Existing connections will be closed gracefully, allowing
// in-progress RPCs to complete. A server enters this mode when it does not
// contain the required configuration to serve RPCs.
ServingModeNotServing
)
func (s ServingMode) String() string {
switch s {
case ServingModeStarting:
return "STARTING"
case ServingModeServing:
return "SERVING"
case ServingModeNotServing:
return "NOT_SERVING"
default:
logger.Errorf("unknown serving mode: %d", s)
return "INVALID_MODE"
}
}

View File

@@ -140,6 +140,11 @@ type TransportCredentials interface {
// Additionally, ClientHandshakeInfo data will be available via the context // Additionally, ClientHandshakeInfo data will be available via the context
// passed to this call. // passed to this call.
// //
// The second argument to this method is the `:authority` header value used
// while creating new streams on this connection after authentication
// succeeds. Implementations must use this as the server name during the
// authentication handshake.
//
// If the returned net.Conn is closed, it MUST close the net.Conn provided. // If the returned net.Conn is closed, it MUST close the net.Conn provided.
ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error) ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
// ServerHandshake does the authentication handshake for servers. It returns // ServerHandshake does the authentication handshake for servers. It returns
@@ -153,9 +158,13 @@ type TransportCredentials interface {
Info() ProtocolInfo Info() ProtocolInfo
// Clone makes a copy of this TransportCredentials. // Clone makes a copy of this TransportCredentials.
Clone() TransportCredentials Clone() TransportCredentials
// OverrideServerName overrides the server name used to verify the hostname on the returned certificates from the server. // OverrideServerName specifies the value used for the following:
// gRPC internals also use it to override the virtual hosting name if it is set. // - verifying the hostname on the returned certificates
// It must be called before dialing. Currently, this is only used by grpclb. // - as SNI in the client's handshake to support virtual hosting
// - as the value for `:authority` header at stream creation time
//
// Deprecated: use grpc.WithAuthority instead. Will be supported
// throughout 1.x.
OverrideServerName(string) error OverrideServerName(string) error
} }
@@ -169,8 +178,18 @@ type TransportCredentials interface {
// //
// This API is experimental. // This API is experimental.
type Bundle interface { type Bundle interface {
// TransportCredentials returns the transport credentials from the Bundle.
//
// Implementations must return non-nil transport credentials. If transport
// security is not needed by the Bundle, implementations may choose to
// return insecure.NewCredentials().
TransportCredentials() TransportCredentials TransportCredentials() TransportCredentials
// PerRPCCredentials returns the per-RPC credentials from the Bundle.
//
// May be nil if per-RPC credentials are not needed.
PerRPCCredentials() PerRPCCredentials PerRPCCredentials() PerRPCCredentials
// NewWithMode should make a copy of Bundle, and switch mode. Modifying the // NewWithMode should make a copy of Bundle, and switch mode. Modifying the
// existing Bundle may cause races. // existing Bundle may cause races.
// //

View File

@@ -1,30 +0,0 @@
// +build go1.12
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package credentials
import "crypto/tls"
// This init function adds cipher suite constants only defined in Go 1.12.
func init() {
cipherSuiteLookup[tls.TLS_AES_128_GCM_SHA256] = "TLS_AES_128_GCM_SHA256"
cipherSuiteLookup[tls.TLS_AES_256_GCM_SHA384] = "TLS_AES_256_GCM_SHA384"
cipherSuiteLookup[tls.TLS_CHACHA20_POLY1305_SHA256] = "TLS_CHACHA20_POLY1305_SHA256"
}

View File

@@ -0,0 +1,98 @@
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package insecure provides an implementation of the
// credentials.TransportCredentials interface which disables transport security.
package insecure
import (
"context"
"net"
"google.golang.org/grpc/credentials"
)
// NewCredentials returns a credentials which disables transport security.
//
// Note that using this credentials with per-RPC credentials which require
// transport security is incompatible and will cause grpc.Dial() to fail.
func NewCredentials() credentials.TransportCredentials {
return insecureTC{}
}
// insecureTC implements the insecure transport credentials. The handshake
// methods simply return the passed in net.Conn and set the security level to
// NoSecurity.
type insecureTC struct{}
func (insecureTC) ClientHandshake(ctx context.Context, _ string, conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
return conn, info{credentials.CommonAuthInfo{SecurityLevel: credentials.NoSecurity}}, nil
}
func (insecureTC) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
return conn, info{credentials.CommonAuthInfo{SecurityLevel: credentials.NoSecurity}}, nil
}
func (insecureTC) Info() credentials.ProtocolInfo {
return credentials.ProtocolInfo{SecurityProtocol: "insecure"}
}
func (insecureTC) Clone() credentials.TransportCredentials {
return insecureTC{}
}
func (insecureTC) OverrideServerName(string) error {
return nil
}
// info contains the auth information for an insecure connection.
// It implements the AuthInfo interface.
type info struct {
credentials.CommonAuthInfo
}
// AuthType returns the type of info as a string.
func (info) AuthType() string {
return "insecure"
}
// insecureBundle implements an insecure bundle.
// An insecure bundle provides a thin wrapper around insecureTC to support
// the credentials.Bundle interface.
type insecureBundle struct{}
// NewBundle returns a bundle with disabled transport security and no per rpc credential.
func NewBundle() credentials.Bundle {
return insecureBundle{}
}
// NewWithMode returns a new insecure Bundle. The mode is ignored.
func (insecureBundle) NewWithMode(string) (credentials.Bundle, error) {
return insecureBundle{}, nil
}
// PerRPCCredentials returns an nil implementation as insecure
// bundle does not support a per rpc credential.
func (insecureBundle) PerRPCCredentials() credentials.PerRPCCredentials {
return nil
}
// TransportCredentials returns the underlying insecure transport credential.
func (insecureBundle) TransportCredentials() credentials.TransportCredentials {
return NewCredentials()
}

View File

@@ -230,4 +230,7 @@ var cipherSuiteLookup = map[uint16]string{
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
tls.TLS_AES_128_GCM_SHA256: "TLS_AES_128_GCM_SHA256",
tls.TLS_AES_256_GCM_SHA384: "TLS_AES_256_GCM_SHA384",
tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256",
} }

View File

@@ -20,16 +20,15 @@ package grpc
import ( import (
"context" "context"
"fmt"
"net" "net"
"time" "time"
"google.golang.org/grpc/backoff" "google.golang.org/grpc/backoff"
"google.golang.org/grpc/balancer" "google.golang.org/grpc/channelz"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/internal" "google.golang.org/grpc/internal"
internalbackoff "google.golang.org/grpc/internal/backoff" internalbackoff "google.golang.org/grpc/internal/backoff"
"google.golang.org/grpc/internal/envconfig"
"google.golang.org/grpc/internal/transport" "google.golang.org/grpc/internal/transport"
"google.golang.org/grpc/keepalive" "google.golang.org/grpc/keepalive"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
@@ -45,20 +44,17 @@ type dialOptions struct {
chainUnaryInts []UnaryClientInterceptor chainUnaryInts []UnaryClientInterceptor
chainStreamInts []StreamClientInterceptor chainStreamInts []StreamClientInterceptor
cp Compressor cp Compressor
dc Decompressor dc Decompressor
bs internalbackoff.Strategy bs internalbackoff.Strategy
block bool block bool
returnLastError bool returnLastError bool
insecure bool timeout time.Duration
timeout time.Duration scChan <-chan ServiceConfig
scChan <-chan ServiceConfig authority string
authority string copts transport.ConnectOptions
copts transport.ConnectOptions callOptions []CallOption
callOptions []CallOption channelzParentID *channelz.Identifier
// This is used by WithBalancerName dial option.
balancerBuilder balancer.Builder
channelzParentID int64
disableServiceConfig bool disableServiceConfig bool
disableRetry bool disableRetry bool
disableHealthCheck bool disableHealthCheck bool
@@ -196,25 +192,6 @@ func WithDecompressor(dc Decompressor) DialOption {
}) })
} }
// WithBalancerName sets the balancer that the ClientConn will be initialized
// with. Balancer registered with balancerName will be used. This function
// panics if no balancer was registered by balancerName.
//
// The balancer cannot be overridden by balancer option specified by service
// config.
//
// Deprecated: use WithDefaultServiceConfig and WithDisableServiceConfig
// instead. Will be removed in a future 1.x release.
func WithBalancerName(balancerName string) DialOption {
builder := balancer.Get(balancerName)
if builder == nil {
panic(fmt.Sprintf("grpc.WithBalancerName: no balancer is registered for name %v", balancerName))
}
return newFuncDialOption(func(o *dialOptions) {
o.balancerBuilder = builder
})
}
// WithServiceConfig returns a DialOption which has a channel to read the // WithServiceConfig returns a DialOption which has a channel to read the
// service configuration. // service configuration.
// //
@@ -228,18 +205,14 @@ func WithServiceConfig(c <-chan ServiceConfig) DialOption {
}) })
} }
// WithConnectParams configures the dialer to use the provided ConnectParams. // WithConnectParams configures the ClientConn to use the provided ConnectParams
// for creating and maintaining connections to servers.
// //
// The backoff configuration specified as part of the ConnectParams overrides // The backoff configuration specified as part of the ConnectParams overrides
// all defaults specified in // all defaults specified in
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. Consider // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. Consider
// using the backoff.DefaultConfig as a base, in cases where you want to // using the backoff.DefaultConfig as a base, in cases where you want to
// override only a subset of the backoff configuration. // override only a subset of the backoff configuration.
//
// Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release.
func WithConnectParams(p ConnectParams) DialOption { func WithConnectParams(p ConnectParams) DialOption {
return newFuncDialOption(func(o *dialOptions) { return newFuncDialOption(func(o *dialOptions) {
o.bs = internalbackoff.Exponential{Config: p.Backoff} o.bs = internalbackoff.Exponential{Config: p.Backoff}
@@ -277,7 +250,7 @@ func withBackoff(bs internalbackoff.Strategy) DialOption {
}) })
} }
// WithBlock returns a DialOption which makes caller of Dial blocks until the // WithBlock returns a DialOption which makes callers of Dial block until the
// underlying connection is up. Without this, Dial returns immediately and // underlying connection is up. Without this, Dial returns immediately and
// connecting the server happens in background. // connecting the server happens in background.
func WithBlock() DialOption { func WithBlock() DialOption {
@@ -303,11 +276,17 @@ func WithReturnConnectionError() DialOption {
} }
// WithInsecure returns a DialOption which disables transport security for this // WithInsecure returns a DialOption which disables transport security for this
// ClientConn. Note that transport security is required unless WithInsecure is // ClientConn. Under the hood, it uses insecure.NewCredentials().
// set. //
// Note that using this DialOption with per-RPC credentials (through
// WithCredentialsBundle or WithPerRPCCredentials) which require transport
// security is incompatible and will cause grpc.Dial() to fail.
//
// Deprecated: use WithTransportCredentials and insecure.NewCredentials()
// instead. Will be supported throughout 1.x.
func WithInsecure() DialOption { func WithInsecure() DialOption {
return newFuncDialOption(func(o *dialOptions) { return newFuncDialOption(func(o *dialOptions) {
o.insecure = true o.copts.TransportCredentials = insecure.NewCredentials()
}) })
} }
@@ -482,8 +461,7 @@ func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOpt
} }
// WithAuthority returns a DialOption that specifies the value to be used as the // WithAuthority returns a DialOption that specifies the value to be used as the
// :authority pseudo-header. This value only works with WithInsecure and has no // :authority pseudo-header and as the server name in authentication handshake.
// effect if TransportCredentials are present.
func WithAuthority(a string) DialOption { func WithAuthority(a string) DialOption {
return newFuncDialOption(func(o *dialOptions) { return newFuncDialOption(func(o *dialOptions) {
o.authority = a o.authority = a
@@ -498,7 +476,7 @@ func WithAuthority(a string) DialOption {
// //
// Notice: This API is EXPERIMENTAL and may be changed or removed in a // Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release. // later release.
func WithChannelzParentID(id int64) DialOption { func WithChannelzParentID(id *channelz.Identifier) DialOption {
return newFuncDialOption(func(o *dialOptions) { return newFuncDialOption(func(o *dialOptions) {
o.channelzParentID = id o.channelzParentID = id
}) })
@@ -519,14 +497,16 @@ func WithDisableServiceConfig() DialOption {
// WithDefaultServiceConfig returns a DialOption that configures the default // WithDefaultServiceConfig returns a DialOption that configures the default
// service config, which will be used in cases where: // service config, which will be used in cases where:
// //
// 1. WithDisableServiceConfig is also used. // 1. WithDisableServiceConfig is also used, or
// 2. Resolver does not return a service config or if the resolver returns an
// invalid service config.
// //
// Experimental // 2. The name resolver does not provide a service config or provides an
// invalid service config.
// //
// Notice: This API is EXPERIMENTAL and may be changed or removed in a // The parameter s is the JSON representation of the default service config.
// later release. // For more information about service configs, see:
// https://github.com/grpc/grpc/blob/master/doc/service_config.md
// For a simple example of usage, see:
// examples/features/load_balancing/client/main.go
func WithDefaultServiceConfig(s string) DialOption { func WithDefaultServiceConfig(s string) DialOption {
return newFuncDialOption(func(o *dialOptions) { return newFuncDialOption(func(o *dialOptions) {
o.defaultServiceConfigRawJSON = &s o.defaultServiceConfigRawJSON = &s
@@ -538,14 +518,8 @@ func WithDefaultServiceConfig(s string) DialOption {
// will happen automatically if no data is written to the wire or if the RPC is // will happen automatically if no data is written to the wire or if the RPC is
// unprocessed by the remote server. // unprocessed by the remote server.
// //
// Retry support is currently disabled by default, but will be enabled by // Retry support is currently enabled by default, but may be disabled by
// default in the future. Until then, it may be enabled by setting the // setting the environment variable "GRPC_GO_RETRY" to "off".
// environment variable "GRPC_GO_RETRY" to "on".
//
// Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release.
func WithDisableRetry() DialOption { func WithDisableRetry() DialOption {
return newFuncDialOption(func(o *dialOptions) { return newFuncDialOption(func(o *dialOptions) {
o.disableRetry = true o.disableRetry = true
@@ -585,7 +559,6 @@ func withHealthCheckFunc(f internal.HealthChecker) DialOption {
func defaultDialOptions() dialOptions { func defaultDialOptions() dialOptions {
return dialOptions{ return dialOptions{
disableRetry: !envconfig.Retry,
healthCheckFunc: internal.HealthCheckFunc, healthCheckFunc: internal.HealthCheckFunc,
copts: transport.ConnectOptions{ copts: transport.ConnectOptions{
WriteBufferSize: defaultWriteBufSize, WriteBufferSize: defaultWriteBufSize,

View File

@@ -108,7 +108,7 @@ var registeredCodecs = make(map[string]Codec)
// more details. // more details.
// //
// NOTE: this function must only be called during initialization time (i.e. in // NOTE: this function must only be called during initialization time (i.e. in
// an init() function), and is not thread-safe. If multiple Compressors are // an init() function), and is not thread-safe. If multiple Codecs are
// registered with the same name, the one registered last will take effect. // registered with the same name, the one registered last will take effect.
func RegisterCodec(codec Codec) { func RegisterCodec(codec Codec) {
if codec == nil { if codec == nil {

View File

@@ -19,11 +19,14 @@
package grpclog package grpclog
import ( import (
"encoding/json"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"strconv" "strconv"
"strings"
"google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpclog"
) )
@@ -95,8 +98,9 @@ var severityName = []string{
// loggerT is the default logger used by grpclog. // loggerT is the default logger used by grpclog.
type loggerT struct { type loggerT struct {
m []*log.Logger m []*log.Logger
v int v int
jsonFormat bool
} }
// NewLoggerV2 creates a loggerV2 with the provided writers. // NewLoggerV2 creates a loggerV2 with the provided writers.
@@ -105,19 +109,32 @@ type loggerT struct {
// Warning logs will be written to warningW and infoW. // Warning logs will be written to warningW and infoW.
// Info logs will be written to infoW. // Info logs will be written to infoW.
func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 { func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 {
return NewLoggerV2WithVerbosity(infoW, warningW, errorW, 0) return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{})
} }
// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and // NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and
// verbosity level. // verbosity level.
func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 { func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 {
return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{verbose: v})
}
type loggerV2Config struct {
verbose int
jsonFormat bool
}
func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config) LoggerV2 {
var m []*log.Logger var m []*log.Logger
m = append(m, log.New(infoW, severityName[infoLog]+": ", log.LstdFlags)) flag := log.LstdFlags
m = append(m, log.New(io.MultiWriter(infoW, warningW), severityName[warningLog]+": ", log.LstdFlags)) if c.jsonFormat {
flag = 0
}
m = append(m, log.New(infoW, "", flag))
m = append(m, log.New(io.MultiWriter(infoW, warningW), "", flag))
ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal. ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal.
m = append(m, log.New(ew, severityName[errorLog]+": ", log.LstdFlags)) m = append(m, log.New(ew, "", flag))
m = append(m, log.New(ew, severityName[fatalLog]+": ", log.LstdFlags)) m = append(m, log.New(ew, "", flag))
return &loggerT{m: m, v: v} return &loggerT{m: m, v: c.verbose, jsonFormat: c.jsonFormat}
} }
// newLoggerV2 creates a loggerV2 to be used as default logger. // newLoggerV2 creates a loggerV2 to be used as default logger.
@@ -142,58 +159,79 @@ func newLoggerV2() LoggerV2 {
if vl, err := strconv.Atoi(vLevel); err == nil { if vl, err := strconv.Atoi(vLevel); err == nil {
v = vl v = vl
} }
return NewLoggerV2WithVerbosity(infoW, warningW, errorW, v)
jsonFormat := strings.EqualFold(os.Getenv("GRPC_GO_LOG_FORMATTER"), "json")
return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{
verbose: v,
jsonFormat: jsonFormat,
})
}
func (g *loggerT) output(severity int, s string) {
sevStr := severityName[severity]
if !g.jsonFormat {
g.m[severity].Output(2, fmt.Sprintf("%v: %v", sevStr, s))
return
}
// TODO: we can also include the logging component, but that needs more
// (API) changes.
b, _ := json.Marshal(map[string]string{
"severity": sevStr,
"message": s,
})
g.m[severity].Output(2, string(b))
} }
func (g *loggerT) Info(args ...interface{}) { func (g *loggerT) Info(args ...interface{}) {
g.m[infoLog].Print(args...) g.output(infoLog, fmt.Sprint(args...))
} }
func (g *loggerT) Infoln(args ...interface{}) { func (g *loggerT) Infoln(args ...interface{}) {
g.m[infoLog].Println(args...) g.output(infoLog, fmt.Sprintln(args...))
} }
func (g *loggerT) Infof(format string, args ...interface{}) { func (g *loggerT) Infof(format string, args ...interface{}) {
g.m[infoLog].Printf(format, args...) g.output(infoLog, fmt.Sprintf(format, args...))
} }
func (g *loggerT) Warning(args ...interface{}) { func (g *loggerT) Warning(args ...interface{}) {
g.m[warningLog].Print(args...) g.output(warningLog, fmt.Sprint(args...))
} }
func (g *loggerT) Warningln(args ...interface{}) { func (g *loggerT) Warningln(args ...interface{}) {
g.m[warningLog].Println(args...) g.output(warningLog, fmt.Sprintln(args...))
} }
func (g *loggerT) Warningf(format string, args ...interface{}) { func (g *loggerT) Warningf(format string, args ...interface{}) {
g.m[warningLog].Printf(format, args...) g.output(warningLog, fmt.Sprintf(format, args...))
} }
func (g *loggerT) Error(args ...interface{}) { func (g *loggerT) Error(args ...interface{}) {
g.m[errorLog].Print(args...) g.output(errorLog, fmt.Sprint(args...))
} }
func (g *loggerT) Errorln(args ...interface{}) { func (g *loggerT) Errorln(args ...interface{}) {
g.m[errorLog].Println(args...) g.output(errorLog, fmt.Sprintln(args...))
} }
func (g *loggerT) Errorf(format string, args ...interface{}) { func (g *loggerT) Errorf(format string, args ...interface{}) {
g.m[errorLog].Printf(format, args...) g.output(errorLog, fmt.Sprintf(format, args...))
} }
func (g *loggerT) Fatal(args ...interface{}) { func (g *loggerT) Fatal(args ...interface{}) {
g.m[fatalLog].Fatal(args...) g.output(fatalLog, fmt.Sprint(args...))
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit(). os.Exit(1)
} }
func (g *loggerT) Fatalln(args ...interface{}) { func (g *loggerT) Fatalln(args ...interface{}) {
g.m[fatalLog].Fatalln(args...) g.output(fatalLog, fmt.Sprintln(args...))
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit(). os.Exit(1)
} }
func (g *loggerT) Fatalf(format string, args ...interface{}) { func (g *loggerT) Fatalf(format string, args ...interface{}) {
g.m[fatalLog].Fatalf(format, args...) g.output(fatalLog, fmt.Sprintf(format, args...))
// No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit(). os.Exit(1)
} }
func (g *loggerT) V(l int) bool { func (g *loggerT) V(l int) bool {
@@ -210,12 +248,12 @@ func (g *loggerT) V(l int) bool {
// later release. // later release.
type DepthLoggerV2 interface { type DepthLoggerV2 interface {
LoggerV2 LoggerV2
// InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Print. // InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println.
InfoDepth(depth int, args ...interface{}) InfoDepth(depth int, args ...interface{})
// WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Print. // WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println.
WarningDepth(depth int, args ...interface{}) WarningDepth(depth int, args ...interface{})
// ErrorDetph logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Print. // ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println.
ErrorDepth(depth int, args ...interface{}) ErrorDepth(depth int, args ...interface{})
// FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Print. // FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println.
FatalDepth(depth int, args ...interface{}) FatalDepth(depth int, args ...interface{})
} }

View File

@@ -1,6 +0,0 @@
#!/bin/bash
TMP=$(mktemp -d /tmp/sdk.XXX) \
&& curl -o $TMP.zip "https://storage.googleapis.com/appengine-sdks/featured/go_appengine_sdk_linux_amd64-1.9.68.zip" \
&& unzip -q $TMP.zip -d $TMP \
&& export PATH="$PATH:$TMP/go_appengine"

View File

@@ -72,9 +72,12 @@ type UnaryServerInfo struct {
} }
// UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal // UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal
// execution of a unary RPC. If a UnaryHandler returns an error, it should be produced by the // execution of a unary RPC.
// status package, or else gRPC will use codes.Unknown as the status code and err.Error() as //
// the status message of the RPC. // If a UnaryHandler returns an error, it should either be produced by the
// status package, or be one of the context errors. Otherwise, gRPC will use
// codes.Unknown as the status code and err.Error() as the status message of the
// RPC.
type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error) type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)
// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info // UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info

View File

@@ -0,0 +1,382 @@
/*
*
* Copyright 2022 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package gracefulswitch implements a graceful switch load balancer.
package gracefulswitch
import (
"errors"
"fmt"
"sync"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/balancer/base"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/resolver"
)
var errBalancerClosed = errors.New("gracefulSwitchBalancer is closed")
var _ balancer.Balancer = (*Balancer)(nil)
// NewBalancer returns a graceful switch Balancer.
func NewBalancer(cc balancer.ClientConn, opts balancer.BuildOptions) *Balancer {
return &Balancer{
cc: cc,
bOpts: opts,
}
}
// Balancer is a utility to gracefully switch from one balancer to
// a new balancer. It implements the balancer.Balancer interface.
type Balancer struct {
bOpts balancer.BuildOptions
cc balancer.ClientConn
// mu protects the following fields and all fields within balancerCurrent
// and balancerPending. mu does not need to be held when calling into the
// child balancers, as all calls into these children happen only as a direct
// result of a call into the gracefulSwitchBalancer, which are also
// guaranteed to be synchronous. There is one exception: an UpdateState call
// from a child balancer when current and pending are populated can lead to
// calling Close() on the current. To prevent that racing with an
// UpdateSubConnState from the channel, we hold currentMu during Close and
// UpdateSubConnState calls.
mu sync.Mutex
balancerCurrent *balancerWrapper
balancerPending *balancerWrapper
closed bool // set to true when this balancer is closed
// currentMu must be locked before mu. This mutex guards against this
// sequence of events: UpdateSubConnState() called, finds the
// balancerCurrent, gives up lock, updateState comes in, causes Close() on
// balancerCurrent before the UpdateSubConnState is called on the
// balancerCurrent.
currentMu sync.Mutex
}
// swap swaps out the current lb with the pending lb and updates the ClientConn.
// The caller must hold gsb.mu.
func (gsb *Balancer) swap() {
gsb.cc.UpdateState(gsb.balancerPending.lastState)
cur := gsb.balancerCurrent
gsb.balancerCurrent = gsb.balancerPending
gsb.balancerPending = nil
go func() {
gsb.currentMu.Lock()
defer gsb.currentMu.Unlock()
cur.Close()
}()
}
// Helper function that checks if the balancer passed in is current or pending.
// The caller must hold gsb.mu.
func (gsb *Balancer) balancerCurrentOrPending(bw *balancerWrapper) bool {
return bw == gsb.balancerCurrent || bw == gsb.balancerPending
}
// SwitchTo initializes the graceful switch process, which completes based on
// connectivity state changes on the current/pending balancer. Thus, the switch
// process is not complete when this method returns. This method must be called
// synchronously alongside the rest of the balancer.Balancer methods this
// Graceful Switch Balancer implements.
func (gsb *Balancer) SwitchTo(builder balancer.Builder) error {
gsb.mu.Lock()
if gsb.closed {
gsb.mu.Unlock()
return errBalancerClosed
}
bw := &balancerWrapper{
gsb: gsb,
lastState: balancer.State{
ConnectivityState: connectivity.Connecting,
Picker: base.NewErrPicker(balancer.ErrNoSubConnAvailable),
},
subconns: make(map[balancer.SubConn]bool),
}
balToClose := gsb.balancerPending // nil if there is no pending balancer
if gsb.balancerCurrent == nil {
gsb.balancerCurrent = bw
} else {
gsb.balancerPending = bw
}
gsb.mu.Unlock()
balToClose.Close()
// This function takes a builder instead of a balancer because builder.Build
// can call back inline, and this utility needs to handle the callbacks.
newBalancer := builder.Build(bw, gsb.bOpts)
if newBalancer == nil {
// This is illegal and should never happen; we clear the balancerWrapper
// we were constructing if it happens to avoid a potential panic.
gsb.mu.Lock()
if gsb.balancerPending != nil {
gsb.balancerPending = nil
} else {
gsb.balancerCurrent = nil
}
gsb.mu.Unlock()
return balancer.ErrBadResolverState
}
// This write doesn't need to take gsb.mu because this field never gets read
// or written to on any calls from the current or pending. Calls from grpc
// to this balancer are guaranteed to be called synchronously, so this
// bw.Balancer field will never be forwarded to until this SwitchTo()
// function returns.
bw.Balancer = newBalancer
return nil
}
// Returns nil if the graceful switch balancer is closed.
func (gsb *Balancer) latestBalancer() *balancerWrapper {
gsb.mu.Lock()
defer gsb.mu.Unlock()
if gsb.balancerPending != nil {
return gsb.balancerPending
}
return gsb.balancerCurrent
}
// UpdateClientConnState forwards the update to the latest balancer created.
func (gsb *Balancer) UpdateClientConnState(state balancer.ClientConnState) error {
// The resolver data is only relevant to the most recent LB Policy.
balToUpdate := gsb.latestBalancer()
if balToUpdate == nil {
return errBalancerClosed
}
// Perform this call without gsb.mu to prevent deadlocks if the child calls
// back into the channel. The latest balancer can never be closed during a
// call from the channel, even without gsb.mu held.
return balToUpdate.UpdateClientConnState(state)
}
// ResolverError forwards the error to the latest balancer created.
func (gsb *Balancer) ResolverError(err error) {
// The resolver data is only relevant to the most recent LB Policy.
balToUpdate := gsb.latestBalancer()
if balToUpdate == nil {
return
}
// Perform this call without gsb.mu to prevent deadlocks if the child calls
// back into the channel. The latest balancer can never be closed during a
// call from the channel, even without gsb.mu held.
balToUpdate.ResolverError(err)
}
// ExitIdle forwards the call to the latest balancer created.
//
// If the latest balancer does not support ExitIdle, the subConns are
// re-connected to manually.
func (gsb *Balancer) ExitIdle() {
balToUpdate := gsb.latestBalancer()
if balToUpdate == nil {
return
}
// There is no need to protect this read with a mutex, as the write to the
// Balancer field happens in SwitchTo, which completes before this can be
// called.
if ei, ok := balToUpdate.Balancer.(balancer.ExitIdler); ok {
ei.ExitIdle()
return
}
for sc := range balToUpdate.subconns {
sc.Connect()
}
}
// UpdateSubConnState forwards the update to the appropriate child.
func (gsb *Balancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
gsb.currentMu.Lock()
defer gsb.currentMu.Unlock()
gsb.mu.Lock()
// Forward update to the appropriate child. Even if there is a pending
// balancer, the current balancer should continue to get SubConn updates to
// maintain the proper state while the pending is still connecting.
var balToUpdate *balancerWrapper
if gsb.balancerCurrent != nil && gsb.balancerCurrent.subconns[sc] {
balToUpdate = gsb.balancerCurrent
} else if gsb.balancerPending != nil && gsb.balancerPending.subconns[sc] {
balToUpdate = gsb.balancerPending
}
gsb.mu.Unlock()
if balToUpdate == nil {
// SubConn belonged to a stale lb policy that has not yet fully closed,
// or the balancer was already closed.
return
}
balToUpdate.UpdateSubConnState(sc, state)
}
// Close closes any active child balancers.
func (gsb *Balancer) Close() {
gsb.mu.Lock()
gsb.closed = true
currentBalancerToClose := gsb.balancerCurrent
gsb.balancerCurrent = nil
pendingBalancerToClose := gsb.balancerPending
gsb.balancerPending = nil
gsb.mu.Unlock()
currentBalancerToClose.Close()
pendingBalancerToClose.Close()
}
// balancerWrapper wraps a balancer.Balancer, and overrides some Balancer
// methods to help cleanup SubConns created by the wrapped balancer.
//
// It implements the balancer.ClientConn interface and is passed down in that
// capacity to the wrapped balancer. It maintains a set of subConns created by
// the wrapped balancer and calls from the latter to create/update/remove
// SubConns update this set before being forwarded to the parent ClientConn.
// State updates from the wrapped balancer can result in invocation of the
// graceful switch logic.
type balancerWrapper struct {
balancer.Balancer
gsb *Balancer
lastState balancer.State
subconns map[balancer.SubConn]bool // subconns created by this balancer
}
func (bw *balancerWrapper) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
if state.ConnectivityState == connectivity.Shutdown {
bw.gsb.mu.Lock()
delete(bw.subconns, sc)
bw.gsb.mu.Unlock()
}
// There is no need to protect this read with a mutex, as the write to the
// Balancer field happens in SwitchTo, which completes before this can be
// called.
bw.Balancer.UpdateSubConnState(sc, state)
}
// Close closes the underlying LB policy and removes the subconns it created. bw
// must not be referenced via balancerCurrent or balancerPending in gsb when
// called. gsb.mu must not be held. Does not panic with a nil receiver.
func (bw *balancerWrapper) Close() {
// before Close is called.
if bw == nil {
return
}
// There is no need to protect this read with a mutex, as Close() is
// impossible to be called concurrently with the write in SwitchTo(). The
// callsites of Close() for this balancer in Graceful Switch Balancer will
// never be called until SwitchTo() returns.
bw.Balancer.Close()
bw.gsb.mu.Lock()
for sc := range bw.subconns {
bw.gsb.cc.RemoveSubConn(sc)
}
bw.gsb.mu.Unlock()
}
func (bw *balancerWrapper) UpdateState(state balancer.State) {
// Hold the mutex for this entire call to ensure it cannot occur
// concurrently with other updateState() calls. This causes updates to
// lastState and calls to cc.UpdateState to happen atomically.
bw.gsb.mu.Lock()
defer bw.gsb.mu.Unlock()
bw.lastState = state
if !bw.gsb.balancerCurrentOrPending(bw) {
return
}
if bw == bw.gsb.balancerCurrent {
// In the case that the current balancer exits READY, and there is a pending
// balancer, you can forward the pending balancer's cached State up to
// ClientConn and swap the pending into the current. This is because there
// is no reason to gracefully switch from and keep using the old policy as
// the ClientConn is not connected to any backends.
if state.ConnectivityState != connectivity.Ready && bw.gsb.balancerPending != nil {
bw.gsb.swap()
return
}
// Even if there is a pending balancer waiting to be gracefully switched to,
// continue to forward current balancer updates to the Client Conn. Ignoring
// state + picker from the current would cause undefined behavior/cause the
// system to behave incorrectly from the current LB policies perspective.
// Also, the current LB is still being used by grpc to choose SubConns per
// RPC, and thus should use the most updated form of the current balancer.
bw.gsb.cc.UpdateState(state)
return
}
// This method is now dealing with a state update from the pending balancer.
// If the current balancer is currently in a state other than READY, the new
// policy can be swapped into place immediately. This is because there is no
// reason to gracefully switch from and keep using the old policy as the
// ClientConn is not connected to any backends.
if state.ConnectivityState != connectivity.Connecting || bw.gsb.balancerCurrent.lastState.ConnectivityState != connectivity.Ready {
bw.gsb.swap()
}
}
func (bw *balancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
bw.gsb.mu.Lock()
if !bw.gsb.balancerCurrentOrPending(bw) {
bw.gsb.mu.Unlock()
return nil, fmt.Errorf("%T at address %p that called NewSubConn is deleted", bw, bw)
}
bw.gsb.mu.Unlock()
sc, err := bw.gsb.cc.NewSubConn(addrs, opts)
if err != nil {
return nil, err
}
bw.gsb.mu.Lock()
if !bw.gsb.balancerCurrentOrPending(bw) { // balancer was closed during this call
bw.gsb.cc.RemoveSubConn(sc)
bw.gsb.mu.Unlock()
return nil, fmt.Errorf("%T at address %p that called NewSubConn is deleted", bw, bw)
}
bw.subconns[sc] = true
bw.gsb.mu.Unlock()
return sc, nil
}
func (bw *balancerWrapper) ResolveNow(opts resolver.ResolveNowOptions) {
// Ignore ResolveNow requests from anything other than the most recent
// balancer, because older balancers were already removed from the config.
if bw != bw.gsb.latestBalancer() {
return
}
bw.gsb.cc.ResolveNow(opts)
}
func (bw *balancerWrapper) RemoveSubConn(sc balancer.SubConn) {
bw.gsb.mu.Lock()
if !bw.gsb.balancerCurrentOrPending(bw) {
bw.gsb.mu.Unlock()
return
}
bw.gsb.mu.Unlock()
bw.gsb.cc.RemoveSubConn(sc)
}
func (bw *balancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
bw.gsb.mu.Lock()
if !bw.gsb.balancerCurrentOrPending(bw) {
bw.gsb.mu.Unlock()
return
}
bw.gsb.mu.Unlock()
bw.gsb.cc.UpdateAddresses(sc, addrs)
}
func (bw *balancerWrapper) Target() string {
return bw.gsb.cc.Target()
}

View File

@@ -31,7 +31,7 @@ import (
// Logger is the global binary logger. It can be used to get binary logger for // Logger is the global binary logger. It can be used to get binary logger for
// each method. // each method.
type Logger interface { type Logger interface {
getMethodLogger(methodName string) *MethodLogger GetMethodLogger(methodName string) MethodLogger
} }
// binLogger is the global binary logger for the binary. One of this should be // binLogger is the global binary logger for the binary. One of this should be
@@ -49,17 +49,24 @@ func SetLogger(l Logger) {
binLogger = l binLogger = l
} }
// GetLogger gets the binarg logger.
//
// Only call this at init time.
func GetLogger() Logger {
return binLogger
}
// GetMethodLogger returns the methodLogger for the given methodName. // GetMethodLogger returns the methodLogger for the given methodName.
// //
// methodName should be in the format of "/service/method". // methodName should be in the format of "/service/method".
// //
// Each methodLogger returned by this method is a new instance. This is to // Each methodLogger returned by this method is a new instance. This is to
// generate sequence id within the call. // generate sequence id within the call.
func GetMethodLogger(methodName string) *MethodLogger { func GetMethodLogger(methodName string) MethodLogger {
if binLogger == nil { if binLogger == nil {
return nil return nil
} }
return binLogger.getMethodLogger(methodName) return binLogger.GetMethodLogger(methodName)
} }
func init() { func init() {
@@ -68,17 +75,29 @@ func init() {
binLogger = NewLoggerFromConfigString(configStr) binLogger = NewLoggerFromConfigString(configStr)
} }
type methodLoggerConfig struct { // MethodLoggerConfig contains the setting for logging behavior of a method
// logger. Currently, it contains the max length of header and message.
type MethodLoggerConfig struct {
// Max length of header and message. // Max length of header and message.
hdr, msg uint64 Header, Message uint64
}
// LoggerConfig contains the config for loggers to create method loggers.
type LoggerConfig struct {
All *MethodLoggerConfig
Services map[string]*MethodLoggerConfig
Methods map[string]*MethodLoggerConfig
Blacklist map[string]struct{}
} }
type logger struct { type logger struct {
all *methodLoggerConfig config LoggerConfig
services map[string]*methodLoggerConfig }
methods map[string]*methodLoggerConfig
blacklist map[string]struct{} // NewLoggerFromConfig builds a logger with the given LoggerConfig.
func NewLoggerFromConfig(config LoggerConfig) Logger {
return &logger{config: config}
} }
// newEmptyLogger creates an empty logger. The map fields need to be filled in // newEmptyLogger creates an empty logger. The map fields need to be filled in
@@ -88,57 +107,57 @@ func newEmptyLogger() *logger {
} }
// Set method logger for "*". // Set method logger for "*".
func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error { func (l *logger) setDefaultMethodLogger(ml *MethodLoggerConfig) error {
if l.all != nil { if l.config.All != nil {
return fmt.Errorf("conflicting global rules found") return fmt.Errorf("conflicting global rules found")
} }
l.all = ml l.config.All = ml
return nil return nil
} }
// Set method logger for "service/*". // Set method logger for "service/*".
// //
// New methodLogger with same service overrides the old one. // New methodLogger with same service overrides the old one.
func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error { func (l *logger) setServiceMethodLogger(service string, ml *MethodLoggerConfig) error {
if _, ok := l.services[service]; ok { if _, ok := l.config.Services[service]; ok {
return fmt.Errorf("conflicting service rules for service %v found", service) return fmt.Errorf("conflicting service rules for service %v found", service)
} }
if l.services == nil { if l.config.Services == nil {
l.services = make(map[string]*methodLoggerConfig) l.config.Services = make(map[string]*MethodLoggerConfig)
} }
l.services[service] = ml l.config.Services[service] = ml
return nil return nil
} }
// Set method logger for "service/method". // Set method logger for "service/method".
// //
// New methodLogger with same method overrides the old one. // New methodLogger with same method overrides the old one.
func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error { func (l *logger) setMethodMethodLogger(method string, ml *MethodLoggerConfig) error {
if _, ok := l.blacklist[method]; ok { if _, ok := l.config.Blacklist[method]; ok {
return fmt.Errorf("conflicting blacklist rules for method %v found", method) return fmt.Errorf("conflicting blacklist rules for method %v found", method)
} }
if _, ok := l.methods[method]; ok { if _, ok := l.config.Methods[method]; ok {
return fmt.Errorf("conflicting method rules for method %v found", method) return fmt.Errorf("conflicting method rules for method %v found", method)
} }
if l.methods == nil { if l.config.Methods == nil {
l.methods = make(map[string]*methodLoggerConfig) l.config.Methods = make(map[string]*MethodLoggerConfig)
} }
l.methods[method] = ml l.config.Methods[method] = ml
return nil return nil
} }
// Set blacklist method for "-service/method". // Set blacklist method for "-service/method".
func (l *logger) setBlacklist(method string) error { func (l *logger) setBlacklist(method string) error {
if _, ok := l.blacklist[method]; ok { if _, ok := l.config.Blacklist[method]; ok {
return fmt.Errorf("conflicting blacklist rules for method %v found", method) return fmt.Errorf("conflicting blacklist rules for method %v found", method)
} }
if _, ok := l.methods[method]; ok { if _, ok := l.config.Methods[method]; ok {
return fmt.Errorf("conflicting method rules for method %v found", method) return fmt.Errorf("conflicting method rules for method %v found", method)
} }
if l.blacklist == nil { if l.config.Blacklist == nil {
l.blacklist = make(map[string]struct{}) l.config.Blacklist = make(map[string]struct{})
} }
l.blacklist[method] = struct{}{} l.config.Blacklist[method] = struct{}{}
return nil return nil
} }
@@ -148,23 +167,23 @@ func (l *logger) setBlacklist(method string) error {
// //
// Each methodLogger returned by this method is a new instance. This is to // Each methodLogger returned by this method is a new instance. This is to
// generate sequence id within the call. // generate sequence id within the call.
func (l *logger) getMethodLogger(methodName string) *MethodLogger { func (l *logger) GetMethodLogger(methodName string) MethodLogger {
s, m, err := grpcutil.ParseMethod(methodName) s, m, err := grpcutil.ParseMethod(methodName)
if err != nil { if err != nil {
grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err) grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err)
return nil return nil
} }
if ml, ok := l.methods[s+"/"+m]; ok { if ml, ok := l.config.Methods[s+"/"+m]; ok {
return newMethodLogger(ml.hdr, ml.msg) return newMethodLogger(ml.Header, ml.Message)
} }
if _, ok := l.blacklist[s+"/"+m]; ok { if _, ok := l.config.Blacklist[s+"/"+m]; ok {
return nil return nil
} }
if ml, ok := l.services[s]; ok { if ml, ok := l.config.Services[s]; ok {
return newMethodLogger(ml.hdr, ml.msg) return newMethodLogger(ml.Header, ml.Message)
} }
if l.all == nil { if l.config.All == nil {
return nil return nil
} }
return newMethodLogger(l.all.hdr, l.all.msg) return newMethodLogger(l.config.All.Header, l.config.All.Message)
} }

View File

@@ -89,7 +89,7 @@ func (l *logger) fillMethodLoggerWithConfigString(config string) error {
if err != nil { if err != nil {
return fmt.Errorf("invalid config: %q, %v", config, err) return fmt.Errorf("invalid config: %q, %v", config, err)
} }
if err := l.setDefaultMethodLogger(&methodLoggerConfig{hdr: hdr, msg: msg}); err != nil { if err := l.setDefaultMethodLogger(&MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
return fmt.Errorf("invalid config: %v", err) return fmt.Errorf("invalid config: %v", err)
} }
return nil return nil
@@ -104,11 +104,11 @@ func (l *logger) fillMethodLoggerWithConfigString(config string) error {
return fmt.Errorf("invalid header/message length config: %q, %v", suffix, err) return fmt.Errorf("invalid header/message length config: %q, %v", suffix, err)
} }
if m == "*" { if m == "*" {
if err := l.setServiceMethodLogger(s, &methodLoggerConfig{hdr: hdr, msg: msg}); err != nil { if err := l.setServiceMethodLogger(s, &MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
return fmt.Errorf("invalid config: %v", err) return fmt.Errorf("invalid config: %v", err)
} }
} else { } else {
if err := l.setMethodMethodLogger(s+"/"+m, &methodLoggerConfig{hdr: hdr, msg: msg}); err != nil { if err := l.setMethodMethodLogger(s+"/"+m, &MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
return fmt.Errorf("invalid config: %v", err) return fmt.Errorf("invalid config: %v", err)
} }
} }

View File

@@ -48,7 +48,11 @@ func (g *callIDGenerator) reset() {
var idGen callIDGenerator var idGen callIDGenerator
// MethodLogger is the sub-logger for each method. // MethodLogger is the sub-logger for each method.
type MethodLogger struct { type MethodLogger interface {
Log(LogEntryConfig)
}
type methodLogger struct {
headerMaxLen, messageMaxLen uint64 headerMaxLen, messageMaxLen uint64
callID uint64 callID uint64
@@ -57,8 +61,8 @@ type MethodLogger struct {
sink Sink // TODO(blog): make this plugable. sink Sink // TODO(blog): make this plugable.
} }
func newMethodLogger(h, m uint64) *MethodLogger { func newMethodLogger(h, m uint64) *methodLogger {
return &MethodLogger{ return &methodLogger{
headerMaxLen: h, headerMaxLen: h,
messageMaxLen: m, messageMaxLen: m,
@@ -69,8 +73,10 @@ func newMethodLogger(h, m uint64) *MethodLogger {
} }
} }
// Log creates a proto binary log entry, and logs it to the sink. // Build is an internal only method for building the proto message out of the
func (ml *MethodLogger) Log(c LogEntryConfig) { // input event. It's made public to enable other library to reuse as much logic
// in methodLogger as possible.
func (ml *methodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry {
m := c.toProto() m := c.toProto()
timestamp, _ := ptypes.TimestampProto(time.Now()) timestamp, _ := ptypes.TimestampProto(time.Now())
m.Timestamp = timestamp m.Timestamp = timestamp
@@ -85,11 +91,15 @@ func (ml *MethodLogger) Log(c LogEntryConfig) {
case *pb.GrpcLogEntry_Message: case *pb.GrpcLogEntry_Message:
m.PayloadTruncated = ml.truncateMessage(pay.Message) m.PayloadTruncated = ml.truncateMessage(pay.Message)
} }
return m
ml.sink.Write(m)
} }
func (ml *MethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) { // Log creates a proto binary log entry, and logs it to the sink.
func (ml *methodLogger) Log(c LogEntryConfig) {
ml.sink.Write(ml.Build(c))
}
func (ml *methodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
if ml.headerMaxLen == maxUInt { if ml.headerMaxLen == maxUInt {
return false return false
} }
@@ -119,7 +129,7 @@ func (ml *MethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
return truncated return truncated
} }
func (ml *MethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) { func (ml *methodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) {
if ml.messageMaxLen == maxUInt { if ml.messageMaxLen == maxUInt {
return false return false
} }

View File

@@ -24,6 +24,8 @@
package channelz package channelz
import ( import (
"context"
"errors"
"fmt" "fmt"
"sort" "sort"
"sync" "sync"
@@ -49,7 +51,8 @@ var (
// TurnOn turns on channelz data collection. // TurnOn turns on channelz data collection.
func TurnOn() { func TurnOn() {
if !IsOn() { if !IsOn() {
NewChannelzStorage() db.set(newChannelMap())
idGen.reset()
atomic.StoreInt32(&curState, 1) atomic.StoreInt32(&curState, 1)
} }
} }
@@ -94,46 +97,40 @@ func (d *dbWrapper) get() *channelMap {
return d.DB return d.DB
} }
// NewChannelzStorage initializes channelz data storage and id generator. // NewChannelzStorageForTesting initializes channelz data storage and id
// generator for testing purposes.
// //
// This function returns a cleanup function to wait for all channelz state to be reset by the // Returns a cleanup function to be invoked by the test, which waits for up to
// grpc goroutines when those entities get closed. By using this cleanup function, we make sure tests // 10s for all channelz state to be reset by the grpc goroutines when those
// don't mess up each other, i.e. lingering goroutine from previous test doing entity removal happen // entities get closed. This cleanup function helps with ensuring that tests
// to remove some entity just register by the new test, since the id space is the same. // don't mess up each other.
// func NewChannelzStorageForTesting() (cleanup func() error) {
// Note: This function is exported for testing purpose only. User should not call db.set(newChannelMap())
// it in most cases.
func NewChannelzStorage() (cleanup func() error) {
db.set(&channelMap{
topLevelChannels: make(map[int64]struct{}),
channels: make(map[int64]*channel),
listenSockets: make(map[int64]*listenSocket),
normalSockets: make(map[int64]*normalSocket),
servers: make(map[int64]*server),
subChannels: make(map[int64]*subChannel),
})
idGen.reset() idGen.reset()
return func() error { return func() error {
var err error
cm := db.get() cm := db.get()
if cm == nil { if cm == nil {
return nil return nil
} }
for i := 0; i < 1000; i++ {
cm.mu.Lock() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
if len(cm.topLevelChannels) == 0 && len(cm.servers) == 0 && len(cm.channels) == 0 && len(cm.subChannels) == 0 && len(cm.listenSockets) == 0 && len(cm.normalSockets) == 0 { defer cancel()
cm.mu.Unlock() ticker := time.NewTicker(10 * time.Millisecond)
// all things stored in the channelz map have been cleared. defer ticker.Stop()
for {
cm.mu.RLock()
topLevelChannels, servers, channels, subChannels, listenSockets, normalSockets := len(cm.topLevelChannels), len(cm.servers), len(cm.channels), len(cm.subChannels), len(cm.listenSockets), len(cm.normalSockets)
cm.mu.RUnlock()
if err := ctx.Err(); err != nil {
return fmt.Errorf("after 10s the channelz map has not been cleaned up yet, topchannels: %d, servers: %d, channels: %d, subchannels: %d, listen sockets: %d, normal sockets: %d", topLevelChannels, servers, channels, subChannels, listenSockets, normalSockets)
}
if topLevelChannels == 0 && servers == 0 && channels == 0 && subChannels == 0 && listenSockets == 0 && normalSockets == 0 {
return nil return nil
} }
cm.mu.Unlock() <-ticker.C
time.Sleep(10 * time.Millisecond)
} }
cm.mu.Lock()
err = fmt.Errorf("after 10s the channelz map has not been cleaned up yet, topchannels: %d, servers: %d, channels: %d, subchannels: %d, listen sockets: %d, normal sockets: %d", len(cm.topLevelChannels), len(cm.servers), len(cm.channels), len(cm.subChannels), len(cm.listenSockets), len(cm.normalSockets))
cm.mu.Unlock()
return err
} }
} }
@@ -188,54 +185,77 @@ func GetServer(id int64) *ServerMetric {
return db.get().GetServer(id) return db.get().GetServer(id)
} }
// RegisterChannel registers the given channel c in channelz database with ref // RegisterChannel registers the given channel c in the channelz database with
// as its reference name, and add it to the child list of its parent (identified // ref as its reference name, and adds it to the child list of its parent
// by pid). pid = 0 means no parent. It returns the unique channelz tracking id // (identified by pid). pid == nil means no parent.
// assigned to this channel. //
func RegisterChannel(c Channel, pid int64, ref string) int64 { // Returns a unique channelz identifier assigned to this channel.
//
// If channelz is not turned ON, the channelz database is not mutated.
func RegisterChannel(c Channel, pid *Identifier, ref string) *Identifier {
id := idGen.genID() id := idGen.genID()
var parent int64
isTopChannel := true
if pid != nil {
isTopChannel = false
parent = pid.Int()
}
if !IsOn() {
return newIdentifer(RefChannel, id, pid)
}
cn := &channel{ cn := &channel{
refName: ref, refName: ref,
c: c, c: c,
subChans: make(map[int64]string), subChans: make(map[int64]string),
nestedChans: make(map[int64]string), nestedChans: make(map[int64]string),
id: id, id: id,
pid: pid, pid: parent,
trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())}, trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
} }
if pid == 0 { db.get().addChannel(id, cn, isTopChannel, parent)
db.get().addChannel(id, cn, true, pid, ref) return newIdentifer(RefChannel, id, pid)
} else {
db.get().addChannel(id, cn, false, pid, ref)
}
return id
} }
// RegisterSubChannel registers the given channel c in channelz database with ref // RegisterSubChannel registers the given subChannel c in the channelz database
// as its reference name, and add it to the child list of its parent (identified // with ref as its reference name, and adds it to the child list of its parent
// by pid). It returns the unique channelz tracking id assigned to this subchannel. // (identified by pid).
func RegisterSubChannel(c Channel, pid int64, ref string) int64 { //
if pid == 0 { // Returns a unique channelz identifier assigned to this subChannel.
logger.Error("a SubChannel's parent id cannot be 0") //
return 0 // If channelz is not turned ON, the channelz database is not mutated.
func RegisterSubChannel(c Channel, pid *Identifier, ref string) (*Identifier, error) {
if pid == nil {
return nil, errors.New("a SubChannel's parent id cannot be nil")
} }
id := idGen.genID() id := idGen.genID()
if !IsOn() {
return newIdentifer(RefSubChannel, id, pid), nil
}
sc := &subChannel{ sc := &subChannel{
refName: ref, refName: ref,
c: c, c: c,
sockets: make(map[int64]string), sockets: make(map[int64]string),
id: id, id: id,
pid: pid, pid: pid.Int(),
trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())}, trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
} }
db.get().addSubChannel(id, sc, pid, ref) db.get().addSubChannel(id, sc, pid.Int())
return id return newIdentifer(RefSubChannel, id, pid), nil
} }
// RegisterServer registers the given server s in channelz database. It returns // RegisterServer registers the given server s in channelz database. It returns
// the unique channelz tracking id assigned to this server. // the unique channelz tracking id assigned to this server.
func RegisterServer(s Server, ref string) int64 { //
// If channelz is not turned ON, the channelz database is not mutated.
func RegisterServer(s Server, ref string) *Identifier {
id := idGen.genID() id := idGen.genID()
if !IsOn() {
return newIdentifer(RefServer, id, nil)
}
svr := &server{ svr := &server{
refName: ref, refName: ref,
s: s, s: s,
@@ -244,71 +264,92 @@ func RegisterServer(s Server, ref string) int64 {
id: id, id: id,
} }
db.get().addServer(id, svr) db.get().addServer(id, svr)
return id return newIdentifer(RefServer, id, nil)
} }
// RegisterListenSocket registers the given listen socket s in channelz database // RegisterListenSocket registers the given listen socket s in channelz database
// with ref as its reference name, and add it to the child list of its parent // with ref as its reference name, and add it to the child list of its parent
// (identified by pid). It returns the unique channelz tracking id assigned to // (identified by pid). It returns the unique channelz tracking id assigned to
// this listen socket. // this listen socket.
func RegisterListenSocket(s Socket, pid int64, ref string) int64 { //
if pid == 0 { // If channelz is not turned ON, the channelz database is not mutated.
logger.Error("a ListenSocket's parent id cannot be 0") func RegisterListenSocket(s Socket, pid *Identifier, ref string) (*Identifier, error) {
return 0 if pid == nil {
return nil, errors.New("a ListenSocket's parent id cannot be 0")
} }
id := idGen.genID() id := idGen.genID()
ls := &listenSocket{refName: ref, s: s, id: id, pid: pid} if !IsOn() {
db.get().addListenSocket(id, ls, pid, ref) return newIdentifer(RefListenSocket, id, pid), nil
return id }
ls := &listenSocket{refName: ref, s: s, id: id, pid: pid.Int()}
db.get().addListenSocket(id, ls, pid.Int())
return newIdentifer(RefListenSocket, id, pid), nil
} }
// RegisterNormalSocket registers the given normal socket s in channelz database // RegisterNormalSocket registers the given normal socket s in channelz database
// with ref as its reference name, and add it to the child list of its parent // with ref as its reference name, and adds it to the child list of its parent
// (identified by pid). It returns the unique channelz tracking id assigned to // (identified by pid). It returns the unique channelz tracking id assigned to
// this normal socket. // this normal socket.
func RegisterNormalSocket(s Socket, pid int64, ref string) int64 { //
if pid == 0 { // If channelz is not turned ON, the channelz database is not mutated.
logger.Error("a NormalSocket's parent id cannot be 0") func RegisterNormalSocket(s Socket, pid *Identifier, ref string) (*Identifier, error) {
return 0 if pid == nil {
return nil, errors.New("a NormalSocket's parent id cannot be 0")
} }
id := idGen.genID() id := idGen.genID()
ns := &normalSocket{refName: ref, s: s, id: id, pid: pid} if !IsOn() {
db.get().addNormalSocket(id, ns, pid, ref) return newIdentifer(RefNormalSocket, id, pid), nil
return id }
ns := &normalSocket{refName: ref, s: s, id: id, pid: pid.Int()}
db.get().addNormalSocket(id, ns, pid.Int())
return newIdentifer(RefNormalSocket, id, pid), nil
} }
// RemoveEntry removes an entry with unique channelz trakcing id to be id from // RemoveEntry removes an entry with unique channelz tracking id to be id from
// channelz database. // channelz database.
func RemoveEntry(id int64) { //
db.get().removeEntry(id) // If channelz is not turned ON, this function is a no-op.
func RemoveEntry(id *Identifier) {
if !IsOn() {
return
}
db.get().removeEntry(id.Int())
} }
// TraceEventDesc is what the caller of AddTraceEvent should provide to describe the event to be added // TraceEventDesc is what the caller of AddTraceEvent should provide to describe
// to the channel trace. // the event to be added to the channel trace.
// The Parent field is optional. It is used for event that will be recorded in the entity's parent //
// trace also. // The Parent field is optional. It is used for an event that will be recorded
// in the entity's parent trace.
type TraceEventDesc struct { type TraceEventDesc struct {
Desc string Desc string
Severity Severity Severity Severity
Parent *TraceEventDesc Parent *TraceEventDesc
} }
// AddTraceEvent adds trace related to the entity with specified id, using the provided TraceEventDesc. // AddTraceEvent adds trace related to the entity with specified id, using the
func AddTraceEvent(l grpclog.DepthLoggerV2, id int64, depth int, desc *TraceEventDesc) { // provided TraceEventDesc.
for d := desc; d != nil; d = d.Parent { //
switch d.Severity { // If channelz is not turned ON, this will simply log the event descriptions.
case CtUnknown, CtInfo: func AddTraceEvent(l grpclog.DepthLoggerV2, id *Identifier, depth int, desc *TraceEventDesc) {
l.InfoDepth(depth+1, d.Desc) // Log only the trace description associated with the bottom most entity.
case CtWarning: switch desc.Severity {
l.WarningDepth(depth+1, d.Desc) case CtUnknown, CtInfo:
case CtError: l.InfoDepth(depth+1, withParens(id)+desc.Desc)
l.ErrorDepth(depth+1, d.Desc) case CtWarning:
} l.WarningDepth(depth+1, withParens(id)+desc.Desc)
case CtError:
l.ErrorDepth(depth+1, withParens(id)+desc.Desc)
} }
if getMaxTraceEntry() == 0 { if getMaxTraceEntry() == 0 {
return return
} }
db.get().traceEvent(id, desc) if IsOn() {
db.get().traceEvent(id.Int(), desc)
}
} }
// channelMap is the storage data structure for channelz. // channelMap is the storage data structure for channelz.
@@ -326,6 +367,17 @@ type channelMap struct {
normalSockets map[int64]*normalSocket normalSockets map[int64]*normalSocket
} }
func newChannelMap() *channelMap {
return &channelMap{
topLevelChannels: make(map[int64]struct{}),
channels: make(map[int64]*channel),
listenSockets: make(map[int64]*listenSocket),
normalSockets: make(map[int64]*normalSocket),
servers: make(map[int64]*server),
subChannels: make(map[int64]*subChannel),
}
}
func (c *channelMap) addServer(id int64, s *server) { func (c *channelMap) addServer(id int64, s *server) {
c.mu.Lock() c.mu.Lock()
s.cm = c s.cm = c
@@ -333,7 +385,7 @@ func (c *channelMap) addServer(id int64, s *server) {
c.mu.Unlock() c.mu.Unlock()
} }
func (c *channelMap) addChannel(id int64, cn *channel, isTopChannel bool, pid int64, ref string) { func (c *channelMap) addChannel(id int64, cn *channel, isTopChannel bool, pid int64) {
c.mu.Lock() c.mu.Lock()
cn.cm = c cn.cm = c
cn.trace.cm = c cn.trace.cm = c
@@ -346,7 +398,7 @@ func (c *channelMap) addChannel(id int64, cn *channel, isTopChannel bool, pid in
c.mu.Unlock() c.mu.Unlock()
} }
func (c *channelMap) addSubChannel(id int64, sc *subChannel, pid int64, ref string) { func (c *channelMap) addSubChannel(id int64, sc *subChannel, pid int64) {
c.mu.Lock() c.mu.Lock()
sc.cm = c sc.cm = c
sc.trace.cm = c sc.trace.cm = c
@@ -355,7 +407,7 @@ func (c *channelMap) addSubChannel(id int64, sc *subChannel, pid int64, ref stri
c.mu.Unlock() c.mu.Unlock()
} }
func (c *channelMap) addListenSocket(id int64, ls *listenSocket, pid int64, ref string) { func (c *channelMap) addListenSocket(id int64, ls *listenSocket, pid int64) {
c.mu.Lock() c.mu.Lock()
ls.cm = c ls.cm = c
c.listenSockets[id] = ls c.listenSockets[id] = ls
@@ -363,7 +415,7 @@ func (c *channelMap) addListenSocket(id int64, ls *listenSocket, pid int64, ref
c.mu.Unlock() c.mu.Unlock()
} }
func (c *channelMap) addNormalSocket(id int64, ns *normalSocket, pid int64, ref string) { func (c *channelMap) addNormalSocket(id int64, ns *normalSocket, pid int64) {
c.mu.Lock() c.mu.Lock()
ns.cm = c ns.cm = c
c.normalSockets[id] = ns c.normalSockets[id] = ns
@@ -630,7 +682,7 @@ func (c *channelMap) GetServerSockets(id int64, startID int64, maxResults int64)
if count == 0 { if count == 0 {
end = true end = true
} }
var s []*SocketMetric s := make([]*SocketMetric, 0, len(sks))
for _, ns := range sks { for _, ns := range sks {
sm := &SocketMetric{} sm := &SocketMetric{}
sm.SocketData = ns.s.ChannelzMetric() sm.SocketData = ns.s.ChannelzMetric()

75
vendor/google.golang.org/grpc/internal/channelz/id.go generated vendored Normal file
View File

@@ -0,0 +1,75 @@
/*
*
* Copyright 2022 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package channelz
import "fmt"
// Identifier is an opaque identifier which uniquely identifies an entity in the
// channelz database.
type Identifier struct {
typ RefChannelType
id int64
str string
pid *Identifier
}
// Type returns the entity type corresponding to id.
func (id *Identifier) Type() RefChannelType {
return id.typ
}
// Int returns the integer identifier corresponding to id.
func (id *Identifier) Int() int64 {
return id.id
}
// String returns a string representation of the entity corresponding to id.
//
// This includes some information about the parent as well. Examples:
// Top-level channel: [Channel #channel-number]
// Nested channel: [Channel #parent-channel-number Channel #channel-number]
// Sub channel: [Channel #parent-channel SubChannel #subchannel-number]
func (id *Identifier) String() string {
return id.str
}
// Equal returns true if other is the same as id.
func (id *Identifier) Equal(other *Identifier) bool {
if (id != nil) != (other != nil) {
return false
}
if id == nil && other == nil {
return true
}
return id.typ == other.typ && id.id == other.id && id.pid == other.pid
}
// NewIdentifierForTesting returns a new opaque identifier to be used only for
// testing purposes.
func NewIdentifierForTesting(typ RefChannelType, id int64, pid *Identifier) *Identifier {
return newIdentifer(typ, id, pid)
}
func newIdentifer(typ RefChannelType, id int64, pid *Identifier) *Identifier {
str := fmt.Sprintf("%s #%d", typ, id)
if pid != nil {
str = fmt.Sprintf("%s %s", pid, str)
}
return &Identifier{typ: typ, id: id, str: str, pid: pid}
}

View File

@@ -26,77 +26,54 @@ import (
var logger = grpclog.Component("channelz") var logger = grpclog.Component("channelz")
func withParens(id *Identifier) string {
return "[" + id.String() + "] "
}
// Info logs and adds a trace event if channelz is on. // Info logs and adds a trace event if channelz is on.
func Info(l grpclog.DepthLoggerV2, id int64, args ...interface{}) { func Info(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
if IsOn() { AddTraceEvent(l, id, 1, &TraceEventDesc{
AddTraceEvent(l, id, 1, &TraceEventDesc{ Desc: fmt.Sprint(args...),
Desc: fmt.Sprint(args...), Severity: CtInfo,
Severity: CtInfo, })
})
} else {
l.InfoDepth(1, args...)
}
} }
// Infof logs and adds a trace event if channelz is on. // Infof logs and adds a trace event if channelz is on.
func Infof(l grpclog.DepthLoggerV2, id int64, format string, args ...interface{}) { func Infof(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...) AddTraceEvent(l, id, 1, &TraceEventDesc{
if IsOn() { Desc: fmt.Sprintf(format, args...),
AddTraceEvent(l, id, 1, &TraceEventDesc{ Severity: CtInfo,
Desc: msg, })
Severity: CtInfo,
})
} else {
l.InfoDepth(1, msg)
}
} }
// Warning logs and adds a trace event if channelz is on. // Warning logs and adds a trace event if channelz is on.
func Warning(l grpclog.DepthLoggerV2, id int64, args ...interface{}) { func Warning(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
if IsOn() { AddTraceEvent(l, id, 1, &TraceEventDesc{
AddTraceEvent(l, id, 1, &TraceEventDesc{ Desc: fmt.Sprint(args...),
Desc: fmt.Sprint(args...), Severity: CtWarning,
Severity: CtWarning, })
})
} else {
l.WarningDepth(1, args...)
}
} }
// Warningf logs and adds a trace event if channelz is on. // Warningf logs and adds a trace event if channelz is on.
func Warningf(l grpclog.DepthLoggerV2, id int64, format string, args ...interface{}) { func Warningf(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...) AddTraceEvent(l, id, 1, &TraceEventDesc{
if IsOn() { Desc: fmt.Sprintf(format, args...),
AddTraceEvent(l, id, 1, &TraceEventDesc{ Severity: CtWarning,
Desc: msg, })
Severity: CtWarning,
})
} else {
l.WarningDepth(1, msg)
}
} }
// Error logs and adds a trace event if channelz is on. // Error logs and adds a trace event if channelz is on.
func Error(l grpclog.DepthLoggerV2, id int64, args ...interface{}) { func Error(l grpclog.DepthLoggerV2, id *Identifier, args ...interface{}) {
if IsOn() { AddTraceEvent(l, id, 1, &TraceEventDesc{
AddTraceEvent(l, id, 1, &TraceEventDesc{ Desc: fmt.Sprint(args...),
Desc: fmt.Sprint(args...), Severity: CtError,
Severity: CtError, })
})
} else {
l.ErrorDepth(1, args...)
}
} }
// Errorf logs and adds a trace event if channelz is on. // Errorf logs and adds a trace event if channelz is on.
func Errorf(l grpclog.DepthLoggerV2, id int64, format string, args ...interface{}) { func Errorf(l grpclog.DepthLoggerV2, id *Identifier, format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...) AddTraceEvent(l, id, 1, &TraceEventDesc{
if IsOn() { Desc: fmt.Sprintf(format, args...),
AddTraceEvent(l, id, 1, &TraceEventDesc{ Severity: CtError,
Desc: msg, })
Severity: CtError,
})
} else {
l.ErrorDepth(1, msg)
}
} }

View File

@@ -686,12 +686,33 @@ const (
type RefChannelType int type RefChannelType int
const ( const (
// RefUnknown indicates an unknown entity type, the zero value for this type.
RefUnknown RefChannelType = iota
// RefChannel indicates the referenced entity is a Channel. // RefChannel indicates the referenced entity is a Channel.
RefChannel RefChannelType = iota RefChannel
// RefSubChannel indicates the referenced entity is a SubChannel. // RefSubChannel indicates the referenced entity is a SubChannel.
RefSubChannel RefSubChannel
// RefServer indicates the referenced entity is a Server.
RefServer
// RefListenSocket indicates the referenced entity is a ListenSocket.
RefListenSocket
// RefNormalSocket indicates the referenced entity is a NormalSocket.
RefNormalSocket
) )
var refChannelTypeToString = map[RefChannelType]string{
RefUnknown: "Unknown",
RefChannel: "Channel",
RefSubChannel: "SubChannel",
RefServer: "Server",
RefListenSocket: "ListenSocket",
RefNormalSocket: "NormalSocket",
}
func (r RefChannelType) String() string {
return refChannelTypeToString[r]
}
func (c *channelTrace) dumpData() *ChannelTrace { func (c *channelTrace) dumpData() *ChannelTrace {
c.mu.Lock() c.mu.Lock()
ct := &ChannelTrace{EventNum: c.eventCount, CreationTime: c.createdTime} ct := &ChannelTrace{EventNum: c.eventCount, CreationTime: c.createdTime}

View File

@@ -1,5 +1,3 @@
// +build !appengine
/* /*
* *
* Copyright 2018 gRPC authors. * Copyright 2018 gRPC authors.

View File

@@ -1,4 +1,5 @@
// +build !linux appengine //go:build !linux
// +build !linux
/* /*
* *
@@ -37,6 +38,6 @@ type SocketOptionData struct {
// Windows OS doesn't support Socket Option // Windows OS doesn't support Socket Option
func (s *SocketOptionData) Getsockopt(fd uintptr) { func (s *SocketOptionData) Getsockopt(fd uintptr) {
once.Do(func() { once.Do(func() {
logger.Warning("Channelz: socket options are not supported on non-linux os and appengine.") logger.Warning("Channelz: socket options are not supported on non-linux environments")
}) })
} }

View File

@@ -1,5 +1,3 @@
// +build linux,!appengine
/* /*
* *
* Copyright 2018 gRPC authors. * Copyright 2018 gRPC authors.

View File

@@ -1,4 +1,5 @@
// +build !linux appengine //go:build !linux
// +build !linux
/* /*
* *

View File

@@ -1,5 +1,3 @@
// +build !appengine
/* /*
* *
* Copyright 2020 gRPC authors. * Copyright 2020 gRPC authors.

View File

@@ -1,31 +0,0 @@
// +build appengine
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package credentials
import (
"crypto/tls"
"net/url"
)
// SPIFFEIDFromState is a no-op for appengine builds.
func SPIFFEIDFromState(state tls.ConnectionState) *url.URL {
return nil
}

View File

@@ -1,5 +1,3 @@
// +build !appengine
/* /*
* *
* Copyright 2018 gRPC authors. * Copyright 2018 gRPC authors.

View File

@@ -18,7 +18,9 @@
package credentials package credentials
import "crypto/tls" import (
"crypto/tls"
)
const alpnProtoStrH2 = "h2" const alpnProtoStrH2 = "h2"

View File

@@ -26,13 +26,10 @@ import (
const ( const (
prefix = "GRPC_GO_" prefix = "GRPC_GO_"
retryStr = prefix + "RETRY"
txtErrIgnoreStr = prefix + "IGNORE_TXT_ERRORS" txtErrIgnoreStr = prefix + "IGNORE_TXT_ERRORS"
) )
var ( var (
// Retry is set if retry is explicitly enabled via "GRPC_GO_RETRY=on".
Retry = strings.EqualFold(os.Getenv(retryStr), "on")
// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false"). // TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
TXTErrIgnore = !strings.EqualFold(os.Getenv(txtErrIgnoreStr), "false") TXTErrIgnore = !strings.EqualFold(os.Getenv(txtErrIgnoreStr), "false")
) )

101
vendor/google.golang.org/grpc/internal/envconfig/xds.go generated vendored Normal file
View File

@@ -0,0 +1,101 @@
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package envconfig
import (
"os"
"strings"
)
const (
// XDSBootstrapFileNameEnv is the env variable to set bootstrap file name.
// Do not use this and read from env directly. Its value is read and kept in
// variable XDSBootstrapFileName.
//
// When both bootstrap FileName and FileContent are set, FileName is used.
XDSBootstrapFileNameEnv = "GRPC_XDS_BOOTSTRAP"
// XDSBootstrapFileContentEnv is the env variable to set bootstrap file
// content. Do not use this and read from env directly. Its value is read
// and kept in variable XDSBootstrapFileContent.
//
// When both bootstrap FileName and FileContent are set, FileName is used.
XDSBootstrapFileContentEnv = "GRPC_XDS_BOOTSTRAP_CONFIG"
ringHashSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH"
clientSideSecuritySupportEnv = "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"
aggregateAndDNSSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"
rbacSupportEnv = "GRPC_XDS_EXPERIMENTAL_RBAC"
outlierDetectionSupportEnv = "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION"
federationEnv = "GRPC_EXPERIMENTAL_XDS_FEDERATION"
rlsInXDSEnv = "GRPC_EXPERIMENTAL_XDS_RLS_LB"
c2pResolverTestOnlyTrafficDirectorURIEnv = "GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI"
)
var (
// XDSBootstrapFileName holds the name of the file which contains xDS
// bootstrap configuration. Users can specify the location of the bootstrap
// file by setting the environment variable "GRPC_XDS_BOOTSTRAP".
//
// When both bootstrap FileName and FileContent are set, FileName is used.
XDSBootstrapFileName = os.Getenv(XDSBootstrapFileNameEnv)
// XDSBootstrapFileContent holds the content of the xDS bootstrap
// configuration. Users can specify the bootstrap config by setting the
// environment variable "GRPC_XDS_BOOTSTRAP_CONFIG".
//
// When both bootstrap FileName and FileContent are set, FileName is used.
XDSBootstrapFileContent = os.Getenv(XDSBootstrapFileContentEnv)
// XDSRingHash indicates whether ring hash support is enabled, which can be
// disabled by setting the environment variable
// "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH" to "false".
XDSRingHash = !strings.EqualFold(os.Getenv(ringHashSupportEnv), "false")
// XDSClientSideSecurity is used to control processing of security
// configuration on the client-side.
//
// Note that there is no env var protection for the server-side because we
// have a brand new API on the server-side and users explicitly need to use
// the new API to get security integration on the server.
XDSClientSideSecurity = !strings.EqualFold(os.Getenv(clientSideSecuritySupportEnv), "false")
// XDSAggregateAndDNS indicates whether processing of aggregated cluster
// and DNS cluster is enabled, which can be enabled by setting the
// environment variable
// "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" to
// "true".
XDSAggregateAndDNS = strings.EqualFold(os.Getenv(aggregateAndDNSSupportEnv), "true")
// XDSRBAC indicates whether xDS configured RBAC HTTP Filter is enabled,
// which can be disabled by setting the environment variable
// "GRPC_XDS_EXPERIMENTAL_RBAC" to "false".
XDSRBAC = !strings.EqualFold(os.Getenv(rbacSupportEnv), "false")
// XDSOutlierDetection indicates whether outlier detection support is
// enabled, which can be enabled by setting the environment variable
// "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" to "true".
XDSOutlierDetection = strings.EqualFold(os.Getenv(outlierDetectionSupportEnv), "true")
// XDSFederation indicates whether federation support is enabled.
XDSFederation = strings.EqualFold(os.Getenv(federationEnv), "true")
// XDSRLS indicates whether processing of Cluster Specifier plugins and
// support for the RLS CLuster Specifier is enabled, which can be enabled by
// setting the environment variable "GRPC_EXPERIMENTAL_XDS_RLS_LB" to
// "true".
XDSRLS = strings.EqualFold(os.Getenv(rlsInXDSEnv), "true")
// C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing.
C2PResolverTestOnlyTrafficDirectorURI = os.Getenv(c2pResolverTestOnlyTrafficDirectorURIEnv)
)

View File

@@ -115,12 +115,12 @@ type LoggerV2 interface {
// Notice: This type is EXPERIMENTAL and may be changed or removed in a // Notice: This type is EXPERIMENTAL and may be changed or removed in a
// later release. // later release.
type DepthLoggerV2 interface { type DepthLoggerV2 interface {
// InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Print. // InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println.
InfoDepth(depth int, args ...interface{}) InfoDepth(depth int, args ...interface{})
// WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Print. // WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println.
WarningDepth(depth int, args ...interface{}) WarningDepth(depth int, args ...interface{})
// ErrorDetph logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Print. // ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println.
ErrorDepth(depth int, args ...interface{}) ErrorDepth(depth int, args ...interface{})
// FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Print. // FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println.
FatalDepth(depth int, args ...interface{}) FatalDepth(depth int, args ...interface{})
} }

View File

@@ -1,8 +1,6 @@
// +build appengine
/* /*
* *
* Copyright 2018 gRPC authors. * Copyright 2021 gRPC authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,13 +16,5 @@
* *
*/ */
package credentials // Package grpcutil provides utility functions used across the gRPC codebase.
package grpcutil
import (
"net"
)
// WrapSyscallConn returns newConn on appengine.
func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
return newConn
}

View File

@@ -1,8 +1,6 @@
// +build go1.13
/* /*
* *
* Copyright 2019 gRPC authors. * Copyright 2021 gRPC authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,16 +16,16 @@
* *
*/ */
package dns package grpcutil
import "net" import "regexp"
func init() { // FullMatchWithRegex returns whether the full text matches the regex provided.
filterError = func(err error) error { func FullMatchWithRegex(re *regexp.Regexp, text string) bool {
if dnsErr, ok := err.(*net.DNSError); ok && dnsErr.IsNotFound { if len(text) == 0 {
// The name does not exist; not an error. return re.MatchString(text)
return nil
}
return err
} }
re.Longest()
rem := re.FindString(text)
return len(rem) == len(text)
} }

View File

@@ -1,89 +0,0 @@
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package grpcutil provides a bunch of utility functions to be used across the
// gRPC codebase.
package grpcutil
import (
"strings"
"google.golang.org/grpc/resolver"
)
// split2 returns the values from strings.SplitN(s, sep, 2).
// If sep is not found, it returns ("", "", false) instead.
func split2(s, sep string) (string, string, bool) {
spl := strings.SplitN(s, sep, 2)
if len(spl) < 2 {
return "", "", false
}
return spl[0], spl[1], true
}
// ParseTarget splits target into a resolver.Target struct containing scheme,
// authority and endpoint. skipUnixColonParsing indicates that the parse should
// not parse "unix:[path]" cases. This should be true in cases where a custom
// dialer is present, to prevent a behavior change.
//
// If target is not a valid scheme://authority/endpoint as specified in
// https://github.com/grpc/grpc/blob/master/doc/naming.md,
// it returns {Endpoint: target}.
func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) {
var ok bool
if strings.HasPrefix(target, "unix-abstract:") {
if strings.HasPrefix(target, "unix-abstract://") {
// Maybe, with Authority specified, try to parse it
var remain string
ret.Scheme, remain, _ = split2(target, "://")
ret.Authority, ret.Endpoint, ok = split2(remain, "/")
if !ok {
// No Authority, add the "//" back
ret.Endpoint = "//" + remain
} else {
// Found Authority, add the "/" back
ret.Endpoint = "/" + ret.Endpoint
}
} else {
// Without Authority specified, split target on ":"
ret.Scheme, ret.Endpoint, _ = split2(target, ":")
}
return ret
}
ret.Scheme, ret.Endpoint, ok = split2(target, "://")
if !ok {
if strings.HasPrefix(target, "unix:") && !skipUnixColonParsing {
// Handle the "unix:[local/path]" and "unix:[/absolute/path]" cases,
// because splitting on :// only handles the
// "unix://[/absolute/path]" case. Only handle if the dialer is nil,
// to avoid a behavior change with custom dialers.
return resolver.Target{Scheme: "unix", Endpoint: target[len("unix:"):]}
}
return resolver.Target{Endpoint: target}
}
ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/")
if !ok {
return resolver.Target{Endpoint: target}
}
if ret.Scheme == "unix" {
// Add the "/" back in the unix case, so the unix resolver receives the
// actual endpoint in the "unix://[/absolute/path]" case.
ret.Endpoint = "/" + ret.Endpoint
}
return ret
}

View File

@@ -38,11 +38,10 @@ var (
// KeepaliveMinPingTime is the minimum ping interval. This must be 10s by // KeepaliveMinPingTime is the minimum ping interval. This must be 10s by
// default, but tests may wish to set it lower for convenience. // default, but tests may wish to set it lower for convenience.
KeepaliveMinPingTime = 10 * time.Second KeepaliveMinPingTime = 10 * time.Second
// ParseServiceConfigForTesting is for creating a fake // ParseServiceConfig parses a JSON representation of the service config.
// ClientConn for resolver testing only ParseServiceConfig interface{} // func(string) *serviceconfig.ParseResult
ParseServiceConfigForTesting interface{} // func(string) *serviceconfig.ParseResult
// EqualServiceConfigForTesting is for testing service config generation and // EqualServiceConfigForTesting is for testing service config generation and
// parsing. Both a and b should be returned by ParseServiceConfigForTesting. // parsing. Both a and b should be returned by ParseServiceConfig.
// This function compares the config without rawJSON stripped, in case the // This function compares the config without rawJSON stripped, in case the
// there's difference in white space. // there's difference in white space.
EqualServiceConfigForTesting func(a, b serviceconfig.Config) bool EqualServiceConfigForTesting func(a, b serviceconfig.Config) bool
@@ -86,3 +85,9 @@ const (
// that supports backend returned by grpclb balancer. // that supports backend returned by grpclb balancer.
CredsBundleModeBackendFromBalancer = "backend-from-balancer" CredsBundleModeBackendFromBalancer = "backend-from-balancer"
) )
// RLSLoadBalancingPolicyName is the name of the RLS LB policy.
//
// It currently has an experimental suffix which would be removed once
// end-to-end testing of the policy is completed.
const RLSLoadBalancingPolicyName = "rls_experimental"

View File

@@ -22,6 +22,9 @@
package metadata package metadata
import ( import (
"fmt"
"strings"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
) )
@@ -30,14 +33,38 @@ type mdKeyType string
const mdKey = mdKeyType("grpc.internal.address.metadata") const mdKey = mdKeyType("grpc.internal.address.metadata")
type mdValue metadata.MD
func (m mdValue) Equal(o interface{}) bool {
om, ok := o.(mdValue)
if !ok {
return false
}
if len(m) != len(om) {
return false
}
for k, v := range m {
ov := om[k]
if len(ov) != len(v) {
return false
}
for i, ve := range v {
if ov[i] != ve {
return false
}
}
}
return true
}
// Get returns the metadata of addr. // Get returns the metadata of addr.
func Get(addr resolver.Address) metadata.MD { func Get(addr resolver.Address) metadata.MD {
attrs := addr.Attributes attrs := addr.Attributes
if attrs == nil { if attrs == nil {
return nil return nil
} }
md, _ := attrs.Value(mdKey).(metadata.MD) md, _ := attrs.Value(mdKey).(mdValue)
return md return metadata.MD(md)
} }
// Set sets (overrides) the metadata in addr. // Set sets (overrides) the metadata in addr.
@@ -45,6 +72,49 @@ func Get(addr resolver.Address) metadata.MD {
// When a SubConn is created with this address, the RPCs sent on it will all // When a SubConn is created with this address, the RPCs sent on it will all
// have this metadata. // have this metadata.
func Set(addr resolver.Address, md metadata.MD) resolver.Address { func Set(addr resolver.Address, md metadata.MD) resolver.Address {
addr.Attributes = addr.Attributes.WithValues(mdKey, md) addr.Attributes = addr.Attributes.WithValue(mdKey, mdValue(md))
return addr return addr
} }
// Validate returns an error if the input md contains invalid keys or values.
//
// If the header is not a pseudo-header, the following items are checked:
// - header names must contain one or more characters from this set [0-9 a-z _ - .].
// - if the header-name ends with a "-bin" suffix, no validation of the header value is performed.
// - otherwise, the header value must contain one or more characters from the set [%x20-%x7E].
func Validate(md metadata.MD) error {
for k, vals := range md {
// pseudo-header will be ignored
if k[0] == ':' {
continue
}
// check key, for i that saving a conversion if not using for range
for i := 0; i < len(k); i++ {
r := k[i]
if !(r >= 'a' && r <= 'z') && !(r >= '0' && r <= '9') && r != '.' && r != '-' && r != '_' {
return fmt.Errorf("header key %q contains illegal characters not in [0-9a-z-_.]", k)
}
}
if strings.HasSuffix(k, "-bin") {
continue
}
// check value
for _, val := range vals {
if hasNotPrintable(val) {
return fmt.Errorf("header key %q contains value with non-printable ASCII characters", k)
}
}
}
return nil
}
// hasNotPrintable return true if msg contains any characters which are not in %x20-%x7E
func hasNotPrintable(msg string) bool {
// for i that saving a conversion if not using for range
for i := 0; i < len(msg); i++ {
if msg[i] < 0x20 || msg[i] > 0x7E {
return true
}
}
return false
}

View File

@@ -0,0 +1,82 @@
/*
*
* Copyright 2021 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package pretty defines helper functions to pretty-print structs for logging.
package pretty
import (
"bytes"
"encoding/json"
"fmt"
"github.com/golang/protobuf/jsonpb"
protov1 "github.com/golang/protobuf/proto"
"google.golang.org/protobuf/encoding/protojson"
protov2 "google.golang.org/protobuf/proto"
)
const jsonIndent = " "
// ToJSON marshals the input into a json string.
//
// If marshal fails, it falls back to fmt.Sprintf("%+v").
func ToJSON(e interface{}) string {
switch ee := e.(type) {
case protov1.Message:
mm := jsonpb.Marshaler{Indent: jsonIndent}
ret, err := mm.MarshalToString(ee)
if err != nil {
// This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2
// messages are not imported, and this will fail because the message
// is not found.
return fmt.Sprintf("%+v", ee)
}
return ret
case protov2.Message:
mm := protojson.MarshalOptions{
Multiline: true,
Indent: jsonIndent,
}
ret, err := mm.Marshal(ee)
if err != nil {
// This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2
// messages are not imported, and this will fail because the message
// is not found.
return fmt.Sprintf("%+v", ee)
}
return string(ret)
default:
ret, err := json.MarshalIndent(ee, "", jsonIndent)
if err != nil {
return fmt.Sprintf("%+v", ee)
}
return string(ret)
}
}
// FormatJSON formats the input json bytes with indentation.
//
// If Indent fails, it returns the unchanged input as string.
func FormatJSON(b []byte) string {
var out bytes.Buffer
err := json.Indent(&out, b, "", jsonIndent)
if err != nil {
return string(b)
}
return out.String()
}

View File

@@ -117,9 +117,12 @@ type ClientInterceptor interface {
NewStream(ctx context.Context, ri RPCInfo, done func(), newStream func(ctx context.Context, done func()) (ClientStream, error)) (ClientStream, error) NewStream(ctx context.Context, ri RPCInfo, done func(), newStream func(ctx context.Context, done func()) (ClientStream, error)) (ClientStream, error)
} }
// ServerInterceptor is unimplementable; do not use. // ServerInterceptor is an interceptor for incoming RPC's on gRPC server side.
type ServerInterceptor interface { type ServerInterceptor interface {
notDefined() // AllowRPC checks if an incoming RPC is allowed to proceed based on
// information about connection RPC was received on, and HTTP Headers. This
// information will be piped into context.
AllowRPC(ctx context.Context) error // TODO: Make this a real interceptor for filters such as rate limiting.
} }
type csKeyType string type csKeyType string
@@ -129,7 +132,7 @@ const csKey = csKeyType("grpc.internal.resolver.configSelector")
// SetConfigSelector sets the config selector in state and returns the new // SetConfigSelector sets the config selector in state and returns the new
// state. // state.
func SetConfigSelector(state resolver.State, cs ConfigSelector) resolver.State { func SetConfigSelector(state resolver.State, cs ConfigSelector) resolver.State {
state.Attributes = state.Attributes.WithValues(csKey, cs) state.Attributes = state.Attributes.WithValue(csKey, cs)
return state return state
} }

View File

@@ -277,18 +277,13 @@ func (d *dnsResolver) lookupSRV() ([]resolver.Address, error) {
return newAddrs, nil return newAddrs, nil
} }
var filterError = func(err error) error { func handleDNSError(err error, lookupType string) error {
if dnsErr, ok := err.(*net.DNSError); ok && !dnsErr.IsTimeout && !dnsErr.IsTemporary { if dnsErr, ok := err.(*net.DNSError); ok && !dnsErr.IsTimeout && !dnsErr.IsTemporary {
// Timeouts and temporary errors should be communicated to gRPC to // Timeouts and temporary errors should be communicated to gRPC to
// attempt another DNS query (with backoff). Other errors should be // attempt another DNS query (with backoff). Other errors should be
// suppressed (they may represent the absence of a TXT record). // suppressed (they may represent the absence of a TXT record).
return nil return nil
} }
return err
}
func handleDNSError(err error, lookupType string) error {
err = filterError(err)
if err != nil { if err != nil {
err = fmt.Errorf("dns: %v record lookup error: %v", lookupType, err) err = fmt.Errorf("dns: %v record lookup error: %v", lookupType, err)
logger.Info(err) logger.Info(err)
@@ -323,12 +318,12 @@ func (d *dnsResolver) lookupTXT() *serviceconfig.ParseResult {
} }
func (d *dnsResolver) lookupHost() ([]resolver.Address, error) { func (d *dnsResolver) lookupHost() ([]resolver.Address, error) {
var newAddrs []resolver.Address
addrs, err := d.resolver.LookupHost(d.ctx, d.host) addrs, err := d.resolver.LookupHost(d.ctx, d.host)
if err != nil { if err != nil {
err = handleDNSError(err, "A") err = handleDNSError(err, "A")
return nil, err return nil, err
} }
newAddrs := make([]resolver.Address, 0, len(addrs))
for _, a := range addrs { for _, a := range addrs {
ip, ok := formatIP(a) ip, ok := formatIP(a)
if !ok { if !ok {

View File

@@ -37,7 +37,17 @@ func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolv
if target.Authority != "" { if target.Authority != "" {
return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority) return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority)
} }
addr := resolver.Address{Addr: target.Endpoint}
// gRPC was parsing the dial target manually before PR #4817, and we
// switched to using url.Parse() in that PR. To avoid breaking existing
// resolver implementations we ended up stripping the leading "/" from the
// endpoint. This obviously does not work for the "unix" scheme. Hence we
// end up using the parsed URL instead.
endpoint := target.URL.Path
if endpoint == "" {
endpoint = target.URL.Opaque
}
addr := resolver.Address{Addr: endpoint}
if b.scheme == unixAbstractScheme { if b.scheme == unixAbstractScheme {
// prepend "\x00" to address for unix-abstract // prepend "\x00" to address for unix-abstract
addr.Addr = "\x00" + addr.Addr addr.Addr = "\x00" + addr.Addr

View File

@@ -78,6 +78,7 @@ func (bc *BalancerConfig) UnmarshalJSON(b []byte) error {
return err return err
} }
var names []string
for i, lbcfg := range ir { for i, lbcfg := range ir {
if len(lbcfg) != 1 { if len(lbcfg) != 1 {
return fmt.Errorf("invalid loadBalancingConfig: entry %v does not contain exactly 1 policy/config pair: %q", i, lbcfg) return fmt.Errorf("invalid loadBalancingConfig: entry %v does not contain exactly 1 policy/config pair: %q", i, lbcfg)
@@ -92,6 +93,7 @@ func (bc *BalancerConfig) UnmarshalJSON(b []byte) error {
for name, jsonCfg = range lbcfg { for name, jsonCfg = range lbcfg {
} }
names = append(names, name)
builder := balancer.Get(name) builder := balancer.Get(name)
if builder == nil { if builder == nil {
// If the balancer is not registered, move on to the next config. // If the balancer is not registered, move on to the next config.
@@ -120,7 +122,7 @@ func (bc *BalancerConfig) UnmarshalJSON(b []byte) error {
// return. This means we had a loadBalancingConfig slice but did not // return. This means we had a loadBalancingConfig slice but did not
// encounter a registered policy. The config is considered invalid in this // encounter a registered policy. The config is considered invalid in this
// case. // case.
return fmt.Errorf("invalid loadBalancingConfig: no supported policies found") return fmt.Errorf("invalid loadBalancingConfig: no supported policies found in %v", names)
} }
// MethodConfig defines the configuration recommended by the service providers for a // MethodConfig defines the configuration recommended by the service providers for a

View File

@@ -1,5 +1,3 @@
// +build !appengine
/* /*
* *
* Copyright 2018 gRPC authors. * Copyright 2018 gRPC authors.

View File

@@ -1,4 +1,5 @@
// +build !linux appengine //go:build !linux
// +build !linux
/* /*
* *
@@ -35,41 +36,41 @@ var logger = grpclog.Component("core")
func log() { func log() {
once.Do(func() { once.Do(func() {
logger.Info("CPU time info is unavailable on non-linux or appengine environment.") logger.Info("CPU time info is unavailable on non-linux environments.")
}) })
} }
// GetCPUTime returns the how much CPU time has passed since the start of this process. // GetCPUTime returns the how much CPU time has passed since the start of this
// It always returns 0 under non-linux or appengine environment. // process. It always returns 0 under non-linux environments.
func GetCPUTime() int64 { func GetCPUTime() int64 {
log() log()
return 0 return 0
} }
// Rusage is an empty struct under non-linux or appengine environment. // Rusage is an empty struct under non-linux environments.
type Rusage struct{} type Rusage struct{}
// GetRusage is a no-op function under non-linux or appengine environment. // GetRusage is a no-op function under non-linux environments.
func GetRusage() *Rusage { func GetRusage() *Rusage {
log() log()
return nil return nil
} }
// CPUTimeDiff returns the differences of user CPU time and system CPU time used // CPUTimeDiff returns the differences of user CPU time and system CPU time used
// between two Rusage structs. It a no-op function for non-linux or appengine environment. // between two Rusage structs. It a no-op function for non-linux environments.
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) { func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
log() log()
return 0, 0 return 0, 0
} }
// SetTCPUserTimeout is a no-op function under non-linux or appengine environments // SetTCPUserTimeout is a no-op function under non-linux environments.
func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error { func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
log() log()
return nil return nil
} }
// GetTCPUserTimeout is a no-op function under non-linux or appengine environments // GetTCPUserTimeout is a no-op function under non-linux environments.
// a negative return value indicates the operation is not supported // A negative return value indicates the operation is not supported
func GetTCPUserTimeout(conn net.Conn) (int, error) { func GetTCPUserTimeout(conn net.Conn) (int, error) {
log() log()
return -1, nil return -1, nil

View File

@@ -133,9 +133,11 @@ type cleanupStream struct {
func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM
type earlyAbortStream struct { type earlyAbortStream struct {
httpStatus uint32
streamID uint32 streamID uint32
contentSubtype string contentSubtype string
status *status.Status status *status.Status
rst bool
} }
func (*earlyAbortStream) isTransportResponseFrame() bool { return false } func (*earlyAbortStream) isTransportResponseFrame() bool { return false }
@@ -771,9 +773,12 @@ func (l *loopyWriter) earlyAbortStreamHandler(eas *earlyAbortStream) error {
if l.side == clientSide { if l.side == clientSide {
return errors.New("earlyAbortStream not handled on client") return errors.New("earlyAbortStream not handled on client")
} }
// In case the caller forgets to set the http status, default to 200.
if eas.httpStatus == 0 {
eas.httpStatus = 200
}
headerFields := []hpack.HeaderField{ headerFields := []hpack.HeaderField{
{Name: ":status", Value: "200"}, {Name: ":status", Value: strconv.Itoa(int(eas.httpStatus))},
{Name: "content-type", Value: grpcutil.ContentType(eas.contentSubtype)}, {Name: "content-type", Value: grpcutil.ContentType(eas.contentSubtype)},
{Name: "grpc-status", Value: strconv.Itoa(int(eas.status.Code()))}, {Name: "grpc-status", Value: strconv.Itoa(int(eas.status.Code()))},
{Name: "grpc-message", Value: encodeGrpcMessage(eas.status.Message())}, {Name: "grpc-message", Value: encodeGrpcMessage(eas.status.Message())},
@@ -782,6 +787,11 @@ func (l *loopyWriter) earlyAbortStreamHandler(eas *earlyAbortStream) error {
if err := l.writeHeader(eas.streamID, true, headerFields, nil); err != nil { if err := l.writeHeader(eas.streamID, true, headerFields, nil); err != nil {
return err return err
} }
if eas.rst {
if err := l.framer.fr.WriteRSTStream(eas.streamID, http2.ErrCodeNo); err != nil {
return err
}
}
return nil return nil
} }

View File

@@ -136,12 +136,10 @@ type inFlow struct {
// newLimit updates the inflow window to a new value n. // newLimit updates the inflow window to a new value n.
// It assumes that n is always greater than the old limit. // It assumes that n is always greater than the old limit.
func (f *inFlow) newLimit(n uint32) uint32 { func (f *inFlow) newLimit(n uint32) {
f.mu.Lock() f.mu.Lock()
d := n - f.limit
f.limit = n f.limit = n
f.mu.Unlock() f.mu.Unlock()
return d
} }
func (f *inFlow) maybeAdjust(n uint32) uint32 { func (f *inFlow) maybeAdjust(n uint32) uint32 {

View File

@@ -25,6 +25,7 @@ import (
"math" "math"
"net" "net"
"net/http" "net/http"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@@ -131,7 +132,7 @@ type http2Client struct {
kpDormant bool kpDormant bool
// Fields below are for channelz metric collection. // Fields below are for channelz metric collection.
channelzID int64 // channelz unique identification number channelzID *channelz.Identifier
czData *channelzData czData *channelzData
onGoAway func(GoAwayReason) onGoAway func(GoAwayReason)
@@ -146,13 +147,20 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error
address := addr.Addr address := addr.Addr
networkType, ok := networktype.Get(addr) networkType, ok := networktype.Get(addr)
if fn != nil { if fn != nil {
// Special handling for unix scheme with custom dialer. Back in the day,
// we did not have a unix resolver and therefore targets with a unix
// scheme would end up using the passthrough resolver. So, user's used a
// custom dialer in this case and expected the original dial target to
// be passed to the custom dialer. Now, we have a unix resolver. But if
// a custom dialer is specified, we want to retain the old behavior in
// terms of the address being passed to the custom dialer.
if networkType == "unix" && !strings.HasPrefix(address, "\x00") { if networkType == "unix" && !strings.HasPrefix(address, "\x00") {
// For backward compatibility, if the user dialed "unix:///path", // Supported unix targets are either "unix://absolute-path" or
// the passthrough resolver would be used and the user's custom // "unix:relative-path".
// dialer would see "unix:///path". Since the unix resolver is used if filepath.IsAbs(address) {
// and the address is now "/path", prepend "unix://" so the user's return fn(ctx, "unix://"+address)
// custom dialer sees the same address. }
return fn(ctx, "unix://"+address) return fn(ctx, "unix:"+address)
} }
return fn(ctx, address) return fn(ctx, address)
} }
@@ -193,6 +201,12 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
} }
}() }()
// gRPC, resolver, balancer etc. can specify arbitrary data in the
// Attributes field of resolver.Address, which is shoved into connectCtx
// and passed to the dialer and credential handshaker. This makes it possible for
// address specific arbitrary data to reach custom dialers and credential handshakers.
connectCtx = icredentials.NewClientHandshakeInfoContext(connectCtx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes})
conn, err := dial(connectCtx, opts.Dialer, addr, opts.UseProxy, opts.UserAgent) conn, err := dial(connectCtx, opts.Dialer, addr, opts.UseProxy, opts.UserAgent)
if err != nil { if err != nil {
if opts.FailOnNonTempDialError { if opts.FailOnNonTempDialError {
@@ -237,11 +251,6 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
} }
} }
if transportCreds != nil { if transportCreds != nil {
// gRPC, resolver, balancer etc. can specify arbitrary data in the
// Attributes field of resolver.Address, which is shoved into connectCtx
// and passed to the credential handshaker. This makes it possible for
// address specific arbitrary data to reach the credential handshaker.
connectCtx = icredentials.NewClientHandshakeInfoContext(connectCtx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes})
rawConn := conn rawConn := conn
// Pull the deadline from the connectCtx, which will be used for // Pull the deadline from the connectCtx, which will be used for
// timeouts in the authentication protocol handshake. Can ignore the // timeouts in the authentication protocol handshake. Can ignore the
@@ -342,8 +351,9 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
} }
t.statsHandler.HandleConn(t.ctx, connBegin) t.statsHandler.HandleConn(t.ctx, connBegin)
} }
if channelz.IsOn() { t.channelzID, err = channelz.RegisterNormalSocket(t, opts.ChannelzParentID, fmt.Sprintf("%s -> %s", t.localAddr, t.remoteAddr))
t.channelzID = channelz.RegisterNormalSocket(t, opts.ChannelzParentID, fmt.Sprintf("%s -> %s", t.localAddr, t.remoteAddr)) if err != nil {
return nil, err
} }
if t.keepaliveEnabled { if t.keepaliveEnabled {
t.kpDormancyCond = sync.NewCond(&t.mu) t.kpDormancyCond = sync.NewCond(&t.mu)
@@ -579,7 +589,7 @@ func (t *http2Client) getTrAuthData(ctx context.Context, audience string) (map[s
return nil, err return nil, err
} }
return nil, status.Errorf(codes.Unauthenticated, "transport: %v", err) return nil, status.Errorf(codes.Unauthenticated, "transport: per-RPC creds failed due to error: %v", err)
} }
for k, v := range data { for k, v := range data {
// Capital header names are illegal in HTTP/2. // Capital header names are illegal in HTTP/2.
@@ -616,12 +626,21 @@ func (t *http2Client) getCallAuthData(ctx context.Context, audience string, call
return callAuthData, nil return callAuthData, nil
} }
// NewStreamError wraps an error and reports additional information. // NewStreamError wraps an error and reports additional information. Typically
// NewStream errors result in transparent retry, as they mean nothing went onto
// the wire. However, there are two notable exceptions:
//
// 1. If the stream headers violate the max header list size allowed by the
// server. It's possible this could succeed on another transport, even if
// it's unlikely, but do not transparently retry.
// 2. If the credentials errored when requesting their headers. In this case,
// it's possible a retry can fix the problem, but indefinitely transparently
// retrying is not appropriate as it is likely the credentials, if they can
// eventually succeed, would need I/O to do so.
type NewStreamError struct { type NewStreamError struct {
Err error Err error
DoNotRetry bool AllowTransparentRetry bool
PerformedIO bool
} }
func (e NewStreamError) Error() string { func (e NewStreamError) Error() string {
@@ -630,25 +649,11 @@ func (e NewStreamError) Error() string {
// NewStream creates a stream and registers it into the transport as "active" // NewStream creates a stream and registers it into the transport as "active"
// streams. All non-nil errors returned will be *NewStreamError. // streams. All non-nil errors returned will be *NewStreamError.
func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Stream, err error) { func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) {
defer func() {
if err != nil {
nse, ok := err.(*NewStreamError)
if !ok {
nse = &NewStreamError{Err: err}
}
if len(t.perRPCCreds) > 0 || callHdr.Creds != nil {
// We may have performed I/O in the per-RPC creds callback, so do not
// allow transparent retry.
nse.PerformedIO = true
}
err = nse
}
}()
ctx = peer.NewContext(ctx, t.getPeer()) ctx = peer.NewContext(ctx, t.getPeer())
headerFields, err := t.createHeaderFields(ctx, callHdr) headerFields, err := t.createHeaderFields(ctx, callHdr)
if err != nil { if err != nil {
return nil, err return nil, &NewStreamError{Err: err, AllowTransparentRetry: false}
} }
s := t.newStream(ctx, callHdr) s := t.newStream(ctx, callHdr)
cleanup := func(err error) { cleanup := func(err error) {
@@ -748,23 +753,24 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea
return true return true
}, hdr) }, hdr)
if err != nil { if err != nil {
return nil, err // Connection closed.
return nil, &NewStreamError{Err: err, AllowTransparentRetry: true}
} }
if success { if success {
break break
} }
if hdrListSizeErr != nil { if hdrListSizeErr != nil {
return nil, &NewStreamError{Err: hdrListSizeErr, DoNotRetry: true} return nil, &NewStreamError{Err: hdrListSizeErr}
} }
firstTry = false firstTry = false
select { select {
case <-ch: case <-ch:
case <-s.ctx.Done(): case <-ctx.Done():
return nil, ContextErr(s.ctx.Err()) return nil, &NewStreamError{Err: ContextErr(ctx.Err())}
case <-t.goAway: case <-t.goAway:
return nil, errStreamDrain return nil, &NewStreamError{Err: errStreamDrain, AllowTransparentRetry: true}
case <-t.ctx.Done(): case <-t.ctx.Done():
return nil, ErrConnClosing return nil, &NewStreamError{Err: ErrConnClosing, AllowTransparentRetry: true}
} }
} }
if t.statsHandler != nil { if t.statsHandler != nil {
@@ -893,9 +899,7 @@ func (t *http2Client) Close(err error) {
t.controlBuf.finish() t.controlBuf.finish()
t.cancel() t.cancel()
t.conn.Close() t.conn.Close()
if channelz.IsOn() { channelz.RemoveEntry(t.channelzID)
channelz.RemoveEntry(t.channelzID)
}
// Append info about previous goaways if there were any, since this may be important // Append info about previous goaways if there were any, since this may be important
// for understanding the root cause for this connection to be closed. // for understanding the root cause for this connection to be closed.
_, goAwayDebugMessage := t.GetGoAwayReason() _, goAwayDebugMessage := t.GetGoAwayReason()
@@ -1077,7 +1081,7 @@ func (t *http2Client) handleData(f *http2.DataFrame) {
} }
// The server has closed the stream without sending trailers. Record that // The server has closed the stream without sending trailers. Record that
// the read direction is closed, and set the status appropriately. // the read direction is closed, and set the status appropriately.
if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) { if f.StreamEnded() {
t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.New(codes.Internal, "server closed the stream without sending trailers"), nil, true) t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.New(codes.Internal, "server closed the stream without sending trailers"), nil, true)
} }
} }
@@ -1407,26 +1411,6 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
} }
isHeader := false isHeader := false
defer func() {
if t.statsHandler != nil {
if isHeader {
inHeader := &stats.InHeader{
Client: true,
WireLength: int(frame.Header().Length),
Header: s.header.Copy(),
Compression: s.recvCompress,
}
t.statsHandler.HandleRPC(s.ctx, inHeader)
} else {
inTrailer := &stats.InTrailer{
Client: true,
WireLength: int(frame.Header().Length),
Trailer: s.trailer.Copy(),
}
t.statsHandler.HandleRPC(s.ctx, inTrailer)
}
}
}()
// If headerChan hasn't been closed yet // If headerChan hasn't been closed yet
if atomic.CompareAndSwapUint32(&s.headerChanClosed, 0, 1) { if atomic.CompareAndSwapUint32(&s.headerChanClosed, 0, 1) {
@@ -1448,6 +1432,25 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
close(s.headerChan) close(s.headerChan)
} }
if t.statsHandler != nil {
if isHeader {
inHeader := &stats.InHeader{
Client: true,
WireLength: int(frame.Header().Length),
Header: metadata.MD(mdata).Copy(),
Compression: s.recvCompress,
}
t.statsHandler.HandleRPC(s.ctx, inHeader)
} else {
inTrailer := &stats.InTrailer{
Client: true,
WireLength: int(frame.Header().Length),
Trailer: metadata.MD(mdata).Copy(),
}
t.statsHandler.HandleRPC(s.ctx, inTrailer)
}
}
if !endStream { if !endStream {
return return
} }
@@ -1553,7 +1556,7 @@ func minTime(a, b time.Duration) time.Duration {
return b return b
} }
// keepalive running in a separate goroutune makes sure the connection is alive by sending pings. // keepalive running in a separate goroutine makes sure the connection is alive by sending pings.
func (t *http2Client) keepalive() { func (t *http2Client) keepalive() {
p := &ping{data: [8]byte{}} p := &ping{data: [8]byte{}}
// True iff a ping has been sent, and no data has been received since then. // True iff a ping has been sent, and no data has been received since then.

View File

@@ -21,7 +21,6 @@ package transport
import ( import (
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"math" "math"
@@ -36,6 +35,7 @@ import (
"golang.org/x/net/http2" "golang.org/x/net/http2"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/internal/grpcutil"
"google.golang.org/grpc/internal/syscall"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
@@ -52,10 +52,10 @@ import (
var ( var (
// ErrIllegalHeaderWrite indicates that setting header is illegal because of // ErrIllegalHeaderWrite indicates that setting header is illegal because of
// the stream's state. // the stream's state.
ErrIllegalHeaderWrite = errors.New("transport: the stream is done or WriteHeader was already called") ErrIllegalHeaderWrite = status.Error(codes.Internal, "transport: SendHeader called multiple times")
// ErrHeaderListSizeLimitViolation indicates that the header list size is larger // ErrHeaderListSizeLimitViolation indicates that the header list size is larger
// than the limit set by peer. // than the limit set by peer.
ErrHeaderListSizeLimitViolation = errors.New("transport: trying to send header list size larger than the limit set by peer") ErrHeaderListSizeLimitViolation = status.Error(codes.Internal, "transport: trying to send header list size larger than the limit set by peer")
) )
// serverConnectionCounter counts the number of connections a server has seen // serverConnectionCounter counts the number of connections a server has seen
@@ -73,7 +73,6 @@ type http2Server struct {
writerDone chan struct{} // sync point to enable testing. writerDone chan struct{} // sync point to enable testing.
remoteAddr net.Addr remoteAddr net.Addr
localAddr net.Addr localAddr net.Addr
maxStreamID uint32 // max stream ID ever seen
authInfo credentials.AuthInfo // auth info about the connection authInfo credentials.AuthInfo // auth info about the connection
inTapHandle tap.ServerInHandle inTapHandle tap.ServerInHandle
framer *framer framer *framer
@@ -118,21 +117,42 @@ type http2Server struct {
idle time.Time idle time.Time
// Fields below are for channelz metric collection. // Fields below are for channelz metric collection.
channelzID int64 // channelz unique identification number channelzID *channelz.Identifier
czData *channelzData czData *channelzData
bufferPool *bufferPool bufferPool *bufferPool
connectionID uint64 connectionID uint64
// maxStreamMu guards the maximum stream ID
// This lock may not be taken if mu is already held.
maxStreamMu sync.Mutex
maxStreamID uint32 // max stream ID ever seen
} }
// NewServerTransport creates a http2 transport with conn and configuration // NewServerTransport creates a http2 transport with conn and configuration
// options from config. // options from config.
// //
// It returns a non-nil transport and a nil error on success. On failure, it // It returns a non-nil transport and a nil error on success. On failure, it
// returns a non-nil transport and a nil-error. For a special case where the // returns a nil transport and a non-nil error. For a special case where the
// underlying conn gets closed before the client preface could be read, it // underlying conn gets closed before the client preface could be read, it
// returns a nil transport and a nil error. // returns a nil transport and a nil error.
func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) { func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) {
var authInfo credentials.AuthInfo
rawConn := conn
if config.Credentials != nil {
var err error
conn, authInfo, err = config.Credentials.ServerHandshake(rawConn)
if err != nil {
// ErrConnDispatched means that the connection was dispatched away
// from gRPC; those connections should be left open. io.EOF means
// the connection was closed before handshaking completed, which can
// happen naturally from probers. Return these errors directly.
if err == credentials.ErrConnDispatched || err == io.EOF {
return nil, err
}
return nil, connectionErrorf(false, err, "ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err)
}
}
writeBufSize := config.WriteBufferSize writeBufSize := config.WriteBufferSize
readBufSize := config.ReadBufferSize readBufSize := config.ReadBufferSize
maxHeaderListSize := defaultServerMaxHeaderListSize maxHeaderListSize := defaultServerMaxHeaderListSize
@@ -211,18 +231,24 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
if kp.Timeout == 0 { if kp.Timeout == 0 {
kp.Timeout = defaultServerKeepaliveTimeout kp.Timeout = defaultServerKeepaliveTimeout
} }
if kp.Time != infinity {
if err = syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err)
}
}
kep := config.KeepalivePolicy kep := config.KeepalivePolicy
if kep.MinTime == 0 { if kep.MinTime == 0 {
kep.MinTime = defaultKeepalivePolicyMinTime kep.MinTime = defaultKeepalivePolicyMinTime
} }
done := make(chan struct{}) done := make(chan struct{})
t := &http2Server{ t := &http2Server{
ctx: context.Background(), ctx: setConnection(context.Background(), rawConn),
done: done, done: done,
conn: conn, conn: conn,
remoteAddr: conn.RemoteAddr(), remoteAddr: conn.RemoteAddr(),
localAddr: conn.LocalAddr(), localAddr: conn.LocalAddr(),
authInfo: config.AuthInfo, authInfo: authInfo,
framer: framer, framer: framer,
readerDone: make(chan struct{}), readerDone: make(chan struct{}),
writerDone: make(chan struct{}), writerDone: make(chan struct{}),
@@ -254,12 +280,12 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
connBegin := &stats.ConnBegin{} connBegin := &stats.ConnBegin{}
t.stats.HandleConn(t.ctx, connBegin) t.stats.HandleConn(t.ctx, connBegin)
} }
if channelz.IsOn() { t.channelzID, err = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.remoteAddr, t.localAddr))
t.channelzID = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.remoteAddr, t.localAddr)) if err != nil {
return nil, err
} }
t.connectionID = atomic.AddUint64(&serverConnectionCounter, 1) t.connectionID = atomic.AddUint64(&serverConnectionCounter, 1)
t.framer.writer.Flush() t.framer.writer.Flush()
defer func() { defer func() {
@@ -273,10 +299,11 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
if _, err := io.ReadFull(t.conn, preface); err != nil { if _, err := io.ReadFull(t.conn, preface); err != nil {
// In deployments where a gRPC server runs behind a cloud load balancer // In deployments where a gRPC server runs behind a cloud load balancer
// which performs regular TCP level health checks, the connection is // which performs regular TCP level health checks, the connection is
// closed immediately by the latter. Skipping the error here will help // closed immediately by the latter. Returning io.EOF here allows the
// reduce log clutter. // grpc server implementation to recognize this scenario and suppress
// logging to reduce spam.
if err == io.EOF { if err == io.EOF {
return nil, nil return nil, io.EOF
} }
return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err) return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err)
} }
@@ -316,6 +343,10 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
// operateHeader takes action on the decoded headers. // operateHeader takes action on the decoded headers.
func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) (fatal bool) { func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) (fatal bool) {
// Acquire max stream ID lock for entire duration
t.maxStreamMu.Lock()
defer t.maxStreamMu.Unlock()
streamID := frame.Header().StreamID streamID := frame.Header().StreamID
// frame.Truncated is set to true when framer detects that the current header // frame.Truncated is set to true when framer detects that the current header
@@ -330,6 +361,15 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
return false return false
} }
if streamID%2 != 1 || streamID <= t.maxStreamID {
// illegal gRPC stream id.
if logger.V(logLevel) {
logger.Errorf("transport: http2Server.HandleStreams received an illegal stream id: %v", streamID)
}
return true
}
t.maxStreamID = streamID
buf := newRecvBuffer() buf := newRecvBuffer()
s := &Stream{ s := &Stream{
id: streamID, id: streamID,
@@ -337,7 +377,6 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
buf: buf, buf: buf,
fc: &inFlow{limit: uint32(t.initialWindowSize)}, fc: &inFlow{limit: uint32(t.initialWindowSize)},
} }
var ( var (
// If a gRPC Response-Headers has already been received, then it means // If a gRPC Response-Headers has already been received, then it means
// that the peer is speaking gRPC and we are in gRPC mode. // that the peer is speaking gRPC and we are in gRPC mode.
@@ -373,6 +412,13 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
if timeout, err = decodeTimeout(hf.Value); err != nil { if timeout, err = decodeTimeout(hf.Value); err != nil {
headerError = true headerError = true
} }
// "Transports must consider requests containing the Connection header
// as malformed." - A41
case "connection":
if logger.V(logLevel) {
logger.Errorf("transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec")
}
headerError = true
default: default:
if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) { if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) {
break break
@@ -387,6 +433,26 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
} }
} }
// "If multiple Host headers or multiple :authority headers are present, the
// request must be rejected with an HTTP status code 400 as required by Host
// validation in RFC 7230 §5.4, gRPC status code INTERNAL, or RST_STREAM
// with HTTP/2 error code PROTOCOL_ERROR." - A41. Since this is a HTTP/2
// error, this takes precedence over a client not speaking gRPC.
if len(mdata[":authority"]) > 1 || len(mdata["host"]) > 1 {
errMsg := fmt.Sprintf("num values of :authority: %v, num values of host: %v, both must only have 1 value as per HTTP/2 spec", len(mdata[":authority"]), len(mdata["host"]))
if logger.V(logLevel) {
logger.Errorf("transport: %v", errMsg)
}
t.controlBuf.put(&earlyAbortStream{
httpStatus: 400,
streamID: streamID,
contentSubtype: s.contentSubtype,
status: status.New(codes.Internal, errMsg),
rst: !frame.StreamEnded(),
})
return false
}
if !isGRPC || headerError { if !isGRPC || headerError {
t.controlBuf.put(&cleanupStream{ t.controlBuf.put(&cleanupStream{
streamID: streamID, streamID: streamID,
@@ -397,6 +463,19 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
return false return false
} }
// "If :authority is missing, Host must be renamed to :authority." - A41
if len(mdata[":authority"]) == 0 {
// No-op if host isn't present, no eventual :authority header is a valid
// RPC.
if host, ok := mdata["host"]; ok {
mdata[":authority"] = host
delete(mdata, "host")
}
} else {
// "If :authority is present, Host must be discarded" - A41
delete(mdata, "host")
}
if frame.StreamEnded() { if frame.StreamEnded() {
// s is just created by the caller. No lock needed. // s is just created by the caller. No lock needed.
s.state = streamReadDone s.state = streamReadDone
@@ -441,26 +520,18 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
s.cancel() s.cancel()
return false return false
} }
if streamID%2 != 1 || streamID <= t.maxStreamID {
t.mu.Unlock()
// illegal gRPC stream id.
if logger.V(logLevel) {
logger.Errorf("transport: http2Server.HandleStreams received an illegal stream id: %v", streamID)
}
s.cancel()
return true
}
t.maxStreamID = streamID
if httpMethod != http.MethodPost { if httpMethod != http.MethodPost {
t.mu.Unlock() t.mu.Unlock()
errMsg := fmt.Sprintf("http2Server.operateHeaders parsed a :method field: %v which should be POST", httpMethod)
if logger.V(logLevel) { if logger.V(logLevel) {
logger.Infof("transport: http2Server.operateHeaders parsed a :method field: %v which should be POST", httpMethod) logger.Infof("transport: %v", errMsg)
} }
t.controlBuf.put(&cleanupStream{ t.controlBuf.put(&earlyAbortStream{
streamID: streamID, httpStatus: 405,
rst: true, streamID: streamID,
rstCode: http2.ErrCodeProtocol, contentSubtype: s.contentSubtype,
onWrite: func() {}, status: status.New(codes.Internal, errMsg),
rst: !frame.StreamEnded(),
}) })
s.cancel() s.cancel()
return false return false
@@ -477,9 +548,11 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
stat = status.New(codes.PermissionDenied, err.Error()) stat = status.New(codes.PermissionDenied, err.Error())
} }
t.controlBuf.put(&earlyAbortStream{ t.controlBuf.put(&earlyAbortStream{
httpStatus: 200,
streamID: s.id, streamID: s.id,
contentSubtype: s.contentSubtype, contentSubtype: s.contentSubtype,
status: stat, status: stat,
rst: !frame.StreamEnded(),
}) })
return false return false
} }
@@ -717,7 +790,7 @@ func (t *http2Server) handleData(f *http2.DataFrame) {
s.write(recvMsg{buffer: buffer}) s.write(recvMsg{buffer: buffer})
} }
} }
if f.Header().Flags.Has(http2.FlagDataEndStream) { if f.StreamEnded() {
// Received the end of stream from the client. // Received the end of stream from the client.
s.compareAndSwapState(streamActive, streamReadDone) s.compareAndSwapState(streamActive, streamReadDone)
s.write(recvMsg{err: io.EOF}) s.write(recvMsg{err: io.EOF})
@@ -861,11 +934,25 @@ func (t *http2Server) checkForHeaderListSize(it interface{}) bool {
return true return true
} }
func (t *http2Server) streamContextErr(s *Stream) error {
select {
case <-t.done:
return ErrConnClosing
default:
}
return ContextErr(s.ctx.Err())
}
// WriteHeader sends the header metadata md back to the client. // WriteHeader sends the header metadata md back to the client.
func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error { func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
if s.updateHeaderSent() || s.getState() == streamDone { if s.updateHeaderSent() {
return ErrIllegalHeaderWrite return ErrIllegalHeaderWrite
} }
if s.getState() == streamDone {
return t.streamContextErr(s)
}
s.hdrMu.Lock() s.hdrMu.Lock()
if md.Len() > 0 { if md.Len() > 0 {
if s.header.Len() > 0 { if s.header.Len() > 0 {
@@ -876,7 +963,7 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
} }
if err := t.writeHeaderLocked(s); err != nil { if err := t.writeHeaderLocked(s); err != nil {
s.hdrMu.Unlock() s.hdrMu.Unlock()
return err return status.Convert(err).Err()
} }
s.hdrMu.Unlock() s.hdrMu.Unlock()
return nil return nil
@@ -992,23 +1079,12 @@ func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error {
func (t *http2Server) Write(s *Stream, hdr []byte, data []byte, opts *Options) error { func (t *http2Server) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
if !s.isHeaderSent() { // Headers haven't been written yet. if !s.isHeaderSent() { // Headers haven't been written yet.
if err := t.WriteHeader(s, nil); err != nil { if err := t.WriteHeader(s, nil); err != nil {
if _, ok := err.(ConnectionError); ok { return err
return err
}
// TODO(mmukhi, dfawley): Make sure this is the right code to return.
return status.Errorf(codes.Internal, "transport: %v", err)
} }
} else { } else {
// Writing headers checks for this condition. // Writing headers checks for this condition.
if s.getState() == streamDone { if s.getState() == streamDone {
// TODO(mmukhi, dfawley): Should the server write also return io.EOF? return t.streamContextErr(s)
s.cancel()
select {
case <-t.done:
return ErrConnClosing
default:
}
return ContextErr(s.ctx.Err())
} }
} }
df := &dataFrame{ df := &dataFrame{
@@ -1018,12 +1094,7 @@ func (t *http2Server) Write(s *Stream, hdr []byte, data []byte, opts *Options) e
onEachWrite: t.setResetPingStrikes, onEachWrite: t.setResetPingStrikes,
} }
if err := s.wq.get(int32(len(hdr) + len(data))); err != nil { if err := s.wq.get(int32(len(hdr) + len(data))); err != nil {
select { return t.streamContextErr(s)
case <-t.done:
return ErrConnClosing
default:
}
return ContextErr(s.ctx.Err())
} }
return t.controlBuf.put(df) return t.controlBuf.put(df)
} }
@@ -1146,9 +1217,7 @@ func (t *http2Server) Close() {
if err := t.conn.Close(); err != nil && logger.V(logLevel) { if err := t.conn.Close(); err != nil && logger.V(logLevel) {
logger.Infof("transport: error closing conn during Close: %v", err) logger.Infof("transport: error closing conn during Close: %v", err)
} }
if channelz.IsOn() { channelz.RemoveEntry(t.channelzID)
channelz.RemoveEntry(t.channelzID)
}
// Cancel all active streams. // Cancel all active streams.
for _, s := range streams { for _, s := range streams {
s.cancel() s.cancel()
@@ -1161,10 +1230,6 @@ func (t *http2Server) Close() {
// deleteStream deletes the stream s from transport's active streams. // deleteStream deletes the stream s from transport's active streams.
func (t *http2Server) deleteStream(s *Stream, eosReceived bool) { func (t *http2Server) deleteStream(s *Stream, eosReceived bool) {
// In case stream sending and receiving are invoked in separate
// goroutines (e.g., bi-directional streaming), cancel needs to be
// called to interrupt the potential blocking on other goroutines.
s.cancel()
t.mu.Lock() t.mu.Lock()
if _, ok := t.activeStreams[s.id]; ok { if _, ok := t.activeStreams[s.id]; ok {
@@ -1186,6 +1251,11 @@ func (t *http2Server) deleteStream(s *Stream, eosReceived bool) {
// finishStream closes the stream and puts the trailing headerFrame into controlbuf. // finishStream closes the stream and puts the trailing headerFrame into controlbuf.
func (t *http2Server) finishStream(s *Stream, rst bool, rstCode http2.ErrCode, hdr *headerFrame, eosReceived bool) { func (t *http2Server) finishStream(s *Stream, rst bool, rstCode http2.ErrCode, hdr *headerFrame, eosReceived bool) {
// In case stream sending and receiving are invoked in separate
// goroutines (e.g., bi-directional streaming), cancel needs to be
// called to interrupt the potential blocking on other goroutines.
s.cancel()
oldState := s.swapState(streamDone) oldState := s.swapState(streamDone)
if oldState == streamDone { if oldState == streamDone {
// If the stream was already done, return. // If the stream was already done, return.
@@ -1205,6 +1275,11 @@ func (t *http2Server) finishStream(s *Stream, rst bool, rstCode http2.ErrCode, h
// closeStream clears the footprint of a stream when the stream is not needed any more. // closeStream clears the footprint of a stream when the stream is not needed any more.
func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, eosReceived bool) { func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, eosReceived bool) {
// In case stream sending and receiving are invoked in separate
// goroutines (e.g., bi-directional streaming), cancel needs to be
// called to interrupt the potential blocking on other goroutines.
s.cancel()
s.swapState(streamDone) s.swapState(streamDone)
t.deleteStream(s, eosReceived) t.deleteStream(s, eosReceived)
@@ -1235,20 +1310,23 @@ var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}}
// Handles outgoing GoAway and returns true if loopy needs to put itself // Handles outgoing GoAway and returns true if loopy needs to put itself
// in draining mode. // in draining mode.
func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
t.maxStreamMu.Lock()
t.mu.Lock() t.mu.Lock()
if t.state == closing { // TODO(mmukhi): This seems unnecessary. if t.state == closing { // TODO(mmukhi): This seems unnecessary.
t.mu.Unlock() t.mu.Unlock()
t.maxStreamMu.Unlock()
// The transport is closing. // The transport is closing.
return false, ErrConnClosing return false, ErrConnClosing
} }
sid := t.maxStreamID
if !g.headsUp { if !g.headsUp {
// Stop accepting more streams now. // Stop accepting more streams now.
t.state = draining t.state = draining
sid := t.maxStreamID
if len(t.activeStreams) == 0 { if len(t.activeStreams) == 0 {
g.closeConn = true g.closeConn = true
} }
t.mu.Unlock() t.mu.Unlock()
t.maxStreamMu.Unlock()
if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil { if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil {
return false, err return false, err
} }
@@ -1261,6 +1339,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
return true, nil return true, nil
} }
t.mu.Unlock() t.mu.Unlock()
t.maxStreamMu.Unlock()
// For a graceful close, send out a GoAway with stream ID of MaxUInt32, // For a graceful close, send out a GoAway with stream ID of MaxUInt32,
// Follow that with a ping and wait for the ack to come back or a timer // Follow that with a ping and wait for the ack to come back or a timer
// to expire. During this time accept new streams since they might have // to expire. During this time accept new streams since they might have
@@ -1345,3 +1424,18 @@ func getJitter(v time.Duration) time.Duration {
j := grpcrand.Int63n(2*r) - r j := grpcrand.Int63n(2*r) - r
return time.Duration(j) return time.Duration(j)
} }
type connectionKey struct{}
// GetConnection gets the connection from the context.
func GetConnection(ctx context.Context) net.Conn {
conn, _ := ctx.Value(connectionKey{}).(net.Conn)
return conn
}
// SetConnection adds the connection to the context to be able to get
// information about the destination ip and port for an incoming RPC. This also
// allows any unary or streaming interceptors to see the connection.
func setConnection(ctx context.Context, conn net.Conn) context.Context {
return context.WithValue(ctx, connectionKey{}, conn)
}

View File

@@ -31,7 +31,7 @@ const key = keyType("grpc.internal.transport.networktype")
// Set returns a copy of the provided address with attributes containing networkType. // Set returns a copy of the provided address with attributes containing networkType.
func Set(address resolver.Address, networkType string) resolver.Address { func Set(address resolver.Address, networkType string) resolver.Address {
address.Attributes = address.Attributes.WithValues(key, networkType) address.Attributes = address.Attributes.WithValue(key, networkType)
return address return address
} }

View File

@@ -37,7 +37,7 @@ var (
httpProxyFromEnvironment = http.ProxyFromEnvironment httpProxyFromEnvironment = http.ProxyFromEnvironment
) )
func mapAddress(ctx context.Context, address string) (*url.URL, error) { func mapAddress(address string) (*url.URL, error) {
req := &http.Request{ req := &http.Request{
URL: &url.URL{ URL: &url.URL{
Scheme: "https", Scheme: "https",
@@ -114,7 +114,7 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr stri
// connection. // connection.
func proxyDial(ctx context.Context, addr string, grpcUA string) (conn net.Conn, err error) { func proxyDial(ctx context.Context, addr string, grpcUA string) (conn net.Conn, err error) {
newAddr := addr newAddr := addr
proxyURL, err := mapAddress(ctx, addr) proxyURL, err := mapAddress(addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -30,9 +30,11 @@ import (
"net" "net"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal/channelz"
"google.golang.org/grpc/keepalive" "google.golang.org/grpc/keepalive"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
@@ -518,7 +520,8 @@ const (
// ServerConfig consists of all the configurations to establish a server transport. // ServerConfig consists of all the configurations to establish a server transport.
type ServerConfig struct { type ServerConfig struct {
MaxStreams uint32 MaxStreams uint32
AuthInfo credentials.AuthInfo ConnectionTimeout time.Duration
Credentials credentials.TransportCredentials
InTapHandle tap.ServerInHandle InTapHandle tap.ServerInHandle
StatsHandler stats.Handler StatsHandler stats.Handler
KeepaliveParams keepalive.ServerParameters KeepaliveParams keepalive.ServerParameters
@@ -527,7 +530,7 @@ type ServerConfig struct {
InitialConnWindowSize int32 InitialConnWindowSize int32
WriteBufferSize int WriteBufferSize int
ReadBufferSize int ReadBufferSize int
ChannelzParentID int64 ChannelzParentID *channelz.Identifier
MaxHeaderListSize *uint32 MaxHeaderListSize *uint32
HeaderTableSize *uint32 HeaderTableSize *uint32
} }
@@ -561,7 +564,7 @@ type ConnectOptions struct {
// ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall. // ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall.
ReadBufferSize int ReadBufferSize int
// ChannelzParentID sets the addrConn id which initiate the creation of this client transport. // ChannelzParentID sets the addrConn id which initiate the creation of this client transport.
ChannelzParentID int64 ChannelzParentID *channelz.Identifier
// MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received. // MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received.
MaxHeaderListSize *uint32 MaxHeaderListSize *uint32
// UseProxy specifies if a proxy should be used. // UseProxy specifies if a proxy should be used.
@@ -739,6 +742,12 @@ func (e ConnectionError) Origin() error {
return e.err return e.err
} }
// Unwrap returns the original error of this connection error or nil when the
// origin is nil.
func (e ConnectionError) Unwrap() error {
return e.err
}
var ( var (
// ErrConnClosing indicates that the transport is closing. // ErrConnClosing indicates that the transport is closing.
ErrConnClosing = connectionErrorf(true, nil, "transport is closing") ErrConnClosing = connectionErrorf(true, nil, "transport is closing")

View File

@@ -28,7 +28,7 @@ type handshakeClusterNameKey struct{}
// SetXDSHandshakeClusterName returns a copy of addr in which the Attributes field // SetXDSHandshakeClusterName returns a copy of addr in which the Attributes field
// is updated with the cluster name. // is updated with the cluster name.
func SetXDSHandshakeClusterName(addr resolver.Address, clusterName string) resolver.Address { func SetXDSHandshakeClusterName(addr resolver.Address, clusterName string) resolver.Address {
addr.Attributes = addr.Attributes.WithValues(handshakeClusterNameKey{}, clusterName) addr.Attributes = addr.Attributes.WithValue(handshakeClusterNameKey{}, clusterName)
return addr return addr
} }

View File

@@ -188,7 +188,9 @@ func FromIncomingContext(ctx context.Context) (MD, bool) {
// map, and there's no guarantee that the MD attached to the context is // map, and there's no guarantee that the MD attached to the context is
// created using our helper functions. // created using our helper functions.
key := strings.ToLower(k) key := strings.ToLower(k)
out[key] = v s := make([]string, len(v))
copy(s, v)
out[key] = s
} }
return out, true return out, true
} }
@@ -226,7 +228,9 @@ func FromOutgoingContext(ctx context.Context) (MD, bool) {
// map, and there's no guarantee that the MD attached to the context is // map, and there's no guarantee that the MD attached to the context is
// created using our helper functions. // created using our helper functions.
key := strings.ToLower(k) key := strings.ToLower(k)
out[key] = v s := make([]string, len(v))
copy(s, v)
out[key] = s
} }
for _, added := range raw.added { for _, added := range raw.added {
if len(added)%2 == 1 { if len(added)%2 == 1 {

View File

@@ -131,7 +131,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
} }
if _, ok := status.FromError(err); ok { if _, ok := status.FromError(err); ok {
// Status error: end the RPC unconditionally with this status. // Status error: end the RPC unconditionally with this status.
return nil, nil, err return nil, nil, dropError{error: err}
} }
// For all other errors, wait for ready RPCs should block and other // For all other errors, wait for ready RPCs should block and other
// RPCs should fail with unavailable. // RPCs should fail with unavailable.
@@ -144,7 +144,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
acw, ok := pickResult.SubConn.(*acBalancerWrapper) acw, ok := pickResult.SubConn.(*acBalancerWrapper)
if !ok { if !ok {
logger.Error("subconn returned from pick is not *acBalancerWrapper") logger.Errorf("subconn returned from pick is type %T, not *acBalancerWrapper", pickResult.SubConn)
continue continue
} }
if t := acw.getAddrConn().getReadyTransport(); t != nil { if t := acw.getAddrConn().getReadyTransport(); t != nil {
@@ -175,3 +175,9 @@ func (pw *pickerWrapper) close() {
pw.done = true pw.done = true
close(pw.blockingCh) close(pw.blockingCh)
} }
// dropError is a wrapper error that indicates the LB policy wishes to drop the
// RPC and not retry it.
type dropError struct {
error
}

View File

@@ -44,77 +44,107 @@ func (*pickfirstBuilder) Name() string {
} }
type pickfirstBalancer struct { type pickfirstBalancer struct {
state connectivity.State state connectivity.State
cc balancer.ClientConn cc balancer.ClientConn
sc balancer.SubConn subConn balancer.SubConn
} }
func (b *pickfirstBalancer) ResolverError(err error) { func (b *pickfirstBalancer) ResolverError(err error) {
switch b.state {
case connectivity.TransientFailure, connectivity.Idle, connectivity.Connecting:
// Set a failing picker if we don't have a good picker.
b.cc.UpdateState(balancer.State{ConnectivityState: connectivity.TransientFailure,
Picker: &picker{err: fmt.Errorf("name resolver error: %v", err)},
})
}
if logger.V(2) { if logger.V(2) {
logger.Infof("pickfirstBalancer: ResolverError called with error %v", err) logger.Infof("pickfirstBalancer: ResolverError called with error %v", err)
} }
if b.subConn == nil {
b.state = connectivity.TransientFailure
}
if b.state != connectivity.TransientFailure {
// The picker will not change since the balancer does not currently
// report an error.
return
}
b.cc.UpdateState(balancer.State{
ConnectivityState: connectivity.TransientFailure,
Picker: &picker{err: fmt.Errorf("name resolver error: %v", err)},
})
} }
func (b *pickfirstBalancer) UpdateClientConnState(cs balancer.ClientConnState) error { func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState) error {
if len(cs.ResolverState.Addresses) == 0 { if len(state.ResolverState.Addresses) == 0 {
// The resolver reported an empty address list. Treat it like an error by
// calling b.ResolverError.
if b.subConn != nil {
// Remove the old subConn. All addresses were removed, so it is no longer
// valid.
b.cc.RemoveSubConn(b.subConn)
b.subConn = nil
}
b.ResolverError(errors.New("produced zero addresses")) b.ResolverError(errors.New("produced zero addresses"))
return balancer.ErrBadResolverState return balancer.ErrBadResolverState
} }
if b.sc == nil {
var err error if b.subConn != nil {
b.sc, err = b.cc.NewSubConn(cs.ResolverState.Addresses, balancer.NewSubConnOptions{}) b.cc.UpdateAddresses(b.subConn, state.ResolverState.Addresses)
if err != nil { return nil
if logger.V(2) {
logger.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err)
}
b.state = connectivity.TransientFailure
b.cc.UpdateState(balancer.State{ConnectivityState: connectivity.TransientFailure,
Picker: &picker{err: fmt.Errorf("error creating connection: %v", err)},
})
return balancer.ErrBadResolverState
}
b.state = connectivity.Idle
b.cc.UpdateState(balancer.State{ConnectivityState: connectivity.Idle, Picker: &picker{result: balancer.PickResult{SubConn: b.sc}}})
b.sc.Connect()
} else {
b.cc.UpdateAddresses(b.sc, cs.ResolverState.Addresses)
b.sc.Connect()
} }
subConn, err := b.cc.NewSubConn(state.ResolverState.Addresses, balancer.NewSubConnOptions{})
if err != nil {
if logger.V(2) {
logger.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err)
}
b.state = connectivity.TransientFailure
b.cc.UpdateState(balancer.State{
ConnectivityState: connectivity.TransientFailure,
Picker: &picker{err: fmt.Errorf("error creating connection: %v", err)},
})
return balancer.ErrBadResolverState
}
b.subConn = subConn
b.state = connectivity.Idle
b.cc.UpdateState(balancer.State{
ConnectivityState: connectivity.Idle,
Picker: &picker{result: balancer.PickResult{SubConn: b.subConn}},
})
b.subConn.Connect()
return nil return nil
} }
func (b *pickfirstBalancer) UpdateSubConnState(sc balancer.SubConn, s balancer.SubConnState) { func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state balancer.SubConnState) {
if logger.V(2) { if logger.V(2) {
logger.Infof("pickfirstBalancer: UpdateSubConnState: %p, %v", sc, s) logger.Infof("pickfirstBalancer: UpdateSubConnState: %p, %v", subConn, state)
} }
if b.sc != sc { if b.subConn != subConn {
if logger.V(2) { if logger.V(2) {
logger.Infof("pickfirstBalancer: ignored state change because sc is not recognized") logger.Infof("pickfirstBalancer: ignored state change because subConn is not recognized")
} }
return return
} }
b.state = s.ConnectivityState b.state = state.ConnectivityState
if s.ConnectivityState == connectivity.Shutdown { if state.ConnectivityState == connectivity.Shutdown {
b.sc = nil b.subConn = nil
return return
} }
switch s.ConnectivityState { switch state.ConnectivityState {
case connectivity.Ready, connectivity.Idle: case connectivity.Ready:
b.cc.UpdateState(balancer.State{ConnectivityState: s.ConnectivityState, Picker: &picker{result: balancer.PickResult{SubConn: sc}}}) b.cc.UpdateState(balancer.State{
ConnectivityState: state.ConnectivityState,
Picker: &picker{result: balancer.PickResult{SubConn: subConn}},
})
case connectivity.Connecting: case connectivity.Connecting:
b.cc.UpdateState(balancer.State{ConnectivityState: s.ConnectivityState, Picker: &picker{err: balancer.ErrNoSubConnAvailable}}) b.cc.UpdateState(balancer.State{
ConnectivityState: state.ConnectivityState,
Picker: &picker{err: balancer.ErrNoSubConnAvailable},
})
case connectivity.Idle:
b.cc.UpdateState(balancer.State{
ConnectivityState: state.ConnectivityState,
Picker: &idlePicker{subConn: subConn},
})
case connectivity.TransientFailure: case connectivity.TransientFailure:
b.cc.UpdateState(balancer.State{ b.cc.UpdateState(balancer.State{
ConnectivityState: s.ConnectivityState, ConnectivityState: state.ConnectivityState,
Picker: &picker{err: s.ConnectionError}, Picker: &picker{err: state.ConnectionError},
}) })
} }
} }
@@ -122,15 +152,32 @@ func (b *pickfirstBalancer) UpdateSubConnState(sc balancer.SubConn, s balancer.S
func (b *pickfirstBalancer) Close() { func (b *pickfirstBalancer) Close() {
} }
func (b *pickfirstBalancer) ExitIdle() {
if b.subConn != nil && b.state == connectivity.Idle {
b.subConn.Connect()
}
}
type picker struct { type picker struct {
result balancer.PickResult result balancer.PickResult
err error err error
} }
func (p *picker) Pick(info balancer.PickInfo) (balancer.PickResult, error) { func (p *picker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
return p.result, p.err return p.result, p.err
} }
// idlePicker is used when the SubConn is IDLE and kicks the SubConn into
// CONNECTING when Pick is called.
type idlePicker struct {
subConn balancer.SubConn
}
func (i *idlePicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
i.subConn.Connect()
return balancer.PickResult{}, balancer.ErrNoSubConnAvailable
}
func init() { func init() {
balancer.Register(newPickfirstBuilder()) balancer.Register(newPickfirstBuilder())
} }

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.1.0 // - protoc-gen-go-grpc v1.2.0
// - protoc v3.14.0 // - protoc v3.14.0
// source: reflection/grpc_reflection_v1alpha/reflection.proto // source: reflection/grpc_reflection_v1alpha/reflection.proto

View File

@@ -37,21 +37,17 @@ To register server reflection on a gRPC server:
package reflection // import "google.golang.org/grpc/reflection" package reflection // import "google.golang.org/grpc/reflection"
import ( import (
"bytes"
"compress/gzip"
"fmt"
"io" "io"
"io/ioutil"
"reflect"
"sort" "sort"
"sync"
"github.com/golang/protobuf/proto"
dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
) )
// GRPCServer is the interface provided by a gRPC server. It is implemented by // GRPCServer is the interface provided by a gRPC server. It is implemented by
@@ -59,339 +55,174 @@ import (
// as a registry, for accumulating the services exposed by the server. // as a registry, for accumulating the services exposed by the server.
type GRPCServer interface { type GRPCServer interface {
grpc.ServiceRegistrar grpc.ServiceRegistrar
GetServiceInfo() map[string]grpc.ServiceInfo ServiceInfoProvider
} }
var _ GRPCServer = (*grpc.Server)(nil) var _ GRPCServer = (*grpc.Server)(nil)
type serverReflectionServer struct {
rpb.UnimplementedServerReflectionServer
s GRPCServer
initSymbols sync.Once
serviceNames []string
symbols map[string]*dpb.FileDescriptorProto // map of fully-qualified names to files
}
// Register registers the server reflection service on the given gRPC server. // Register registers the server reflection service on the given gRPC server.
func Register(s GRPCServer) { func Register(s GRPCServer) {
rpb.RegisterServerReflectionServer(s, &serverReflectionServer{ svr := NewServer(ServerOptions{Services: s})
s: s, rpb.RegisterServerReflectionServer(s, svr)
})
} }
// protoMessage is used for type assertion on proto messages. // ServiceInfoProvider is an interface used to retrieve metadata about the
// Generated proto message implements function Descriptor(), but Descriptor() // services to expose.
// is not part of interface proto.Message. This interface is needed to //
// call Descriptor(). // The reflection service is only interested in the service names, but the
type protoMessage interface { // signature is this way so that *grpc.Server implements it. So it is okay
Descriptor() ([]byte, []int) // for a custom implementation to return zero values for the
// grpc.ServiceInfo values in the map.
//
// Experimental
//
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
// later release.
type ServiceInfoProvider interface {
GetServiceInfo() map[string]grpc.ServiceInfo
} }
func (s *serverReflectionServer) getSymbols() (svcNames []string, symbolIndex map[string]*dpb.FileDescriptorProto) { // ExtensionResolver is the interface used to query details about extensions.
s.initSymbols.Do(func() { // This interface is satisfied by protoregistry.GlobalTypes.
serviceInfo := s.s.GetServiceInfo() //
// Experimental
s.symbols = map[string]*dpb.FileDescriptorProto{} //
s.serviceNames = make([]string, 0, len(serviceInfo)) // Notice: This type is EXPERIMENTAL and may be changed or removed in a
processed := map[string]struct{}{} // later release.
for svc, info := range serviceInfo { type ExtensionResolver interface {
s.serviceNames = append(s.serviceNames, svc) protoregistry.ExtensionTypeResolver
fdenc, ok := parseMetadata(info.Metadata) RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
if !ok {
continue
}
fd, err := decodeFileDesc(fdenc)
if err != nil {
continue
}
s.processFile(fd, processed)
}
sort.Strings(s.serviceNames)
})
return s.serviceNames, s.symbols
} }
func (s *serverReflectionServer) processFile(fd *dpb.FileDescriptorProto, processed map[string]struct{}) { // ServerOptions represents the options used to construct a reflection server.
filename := fd.GetName() //
if _, ok := processed[filename]; ok { // Experimental
return //
} // Notice: This type is EXPERIMENTAL and may be changed or removed in a
processed[filename] = struct{}{} // later release.
type ServerOptions struct {
// The source of advertised RPC services. If not specified, the reflection
// server will report an empty list when asked to list services.
//
// This value will typically be a *grpc.Server. But the set of advertised
// services can be customized by wrapping a *grpc.Server or using an
// alternate implementation that returns a custom set of service names.
Services ServiceInfoProvider
// Optional resolver used to load descriptors. If not specified,
// protoregistry.GlobalFiles will be used.
DescriptorResolver protodesc.Resolver
// Optional resolver used to query for known extensions. If not specified,
// protoregistry.GlobalTypes will be used.
ExtensionResolver ExtensionResolver
}
prefix := fd.GetPackage() // NewServer returns a reflection server implementation using the given options.
// This can be used to customize behavior of the reflection service. Most usages
for _, msg := range fd.MessageType { // should prefer to use Register instead.
s.processMessage(fd, prefix, msg) //
// Experimental
//
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
// later release.
func NewServer(opts ServerOptions) rpb.ServerReflectionServer {
if opts.DescriptorResolver == nil {
opts.DescriptorResolver = protoregistry.GlobalFiles
} }
for _, en := range fd.EnumType { if opts.ExtensionResolver == nil {
s.processEnum(fd, prefix, en) opts.ExtensionResolver = protoregistry.GlobalTypes
} }
for _, ext := range fd.Extension { return &serverReflectionServer{
s.processField(fd, prefix, ext) s: opts.Services,
} descResolver: opts.DescriptorResolver,
for _, svc := range fd.Service { extResolver: opts.ExtensionResolver,
svcName := fqn(prefix, svc.GetName())
s.symbols[svcName] = fd
for _, meth := range svc.Method {
name := fqn(svcName, meth.GetName())
s.symbols[name] = fd
}
}
for _, dep := range fd.Dependency {
fdenc := proto.FileDescriptor(dep)
fdDep, err := decodeFileDesc(fdenc)
if err != nil {
continue
}
s.processFile(fdDep, processed)
} }
} }
func (s *serverReflectionServer) processMessage(fd *dpb.FileDescriptorProto, prefix string, msg *dpb.DescriptorProto) { type serverReflectionServer struct {
msgName := fqn(prefix, msg.GetName()) rpb.UnimplementedServerReflectionServer
s.symbols[msgName] = fd s ServiceInfoProvider
descResolver protodesc.Resolver
for _, nested := range msg.NestedType { extResolver ExtensionResolver
s.processMessage(fd, msgName, nested)
}
for _, en := range msg.EnumType {
s.processEnum(fd, msgName, en)
}
for _, ext := range msg.Extension {
s.processField(fd, msgName, ext)
}
for _, fld := range msg.Field {
s.processField(fd, msgName, fld)
}
for _, oneof := range msg.OneofDecl {
oneofName := fqn(msgName, oneof.GetName())
s.symbols[oneofName] = fd
}
}
func (s *serverReflectionServer) processEnum(fd *dpb.FileDescriptorProto, prefix string, en *dpb.EnumDescriptorProto) {
enName := fqn(prefix, en.GetName())
s.symbols[enName] = fd
for _, val := range en.Value {
valName := fqn(enName, val.GetName())
s.symbols[valName] = fd
}
}
func (s *serverReflectionServer) processField(fd *dpb.FileDescriptorProto, prefix string, fld *dpb.FieldDescriptorProto) {
fldName := fqn(prefix, fld.GetName())
s.symbols[fldName] = fd
}
func fqn(prefix, name string) string {
if prefix == "" {
return name
}
return prefix + "." + name
}
// fileDescForType gets the file descriptor for the given type.
// The given type should be a proto message.
func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) {
m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(protoMessage)
if !ok {
return nil, fmt.Errorf("failed to create message from type: %v", st)
}
enc, _ := m.Descriptor()
return decodeFileDesc(enc)
}
// decodeFileDesc does decompression and unmarshalling on the given
// file descriptor byte slice.
func decodeFileDesc(enc []byte) (*dpb.FileDescriptorProto, error) {
raw, err := decompress(enc)
if err != nil {
return nil, fmt.Errorf("failed to decompress enc: %v", err)
}
fd := new(dpb.FileDescriptorProto)
if err := proto.Unmarshal(raw, fd); err != nil {
return nil, fmt.Errorf("bad descriptor: %v", err)
}
return fd, nil
}
// decompress does gzip decompression.
func decompress(b []byte) ([]byte, error) {
r, err := gzip.NewReader(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("bad gzipped descriptor: %v", err)
}
out, err := ioutil.ReadAll(r)
if err != nil {
return nil, fmt.Errorf("bad gzipped descriptor: %v", err)
}
return out, nil
}
func typeForName(name string) (reflect.Type, error) {
pt := proto.MessageType(name)
if pt == nil {
return nil, fmt.Errorf("unknown type: %q", name)
}
st := pt.Elem()
return st, nil
}
func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) {
m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message)
if !ok {
return nil, fmt.Errorf("failed to create message from type: %v", st)
}
var extDesc *proto.ExtensionDesc
for id, desc := range proto.RegisteredExtensions(m) {
if id == ext {
extDesc = desc
break
}
}
if extDesc == nil {
return nil, fmt.Errorf("failed to find registered extension for extension number %v", ext)
}
return decodeFileDesc(proto.FileDescriptor(extDesc.Filename))
}
func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) {
m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message)
if !ok {
return nil, fmt.Errorf("failed to create message from type: %v", st)
}
exts := proto.RegisteredExtensions(m)
out := make([]int32, 0, len(exts))
for id := range exts {
out = append(out, id)
}
return out, nil
} }
// fileDescWithDependencies returns a slice of serialized fileDescriptors in // fileDescWithDependencies returns a slice of serialized fileDescriptors in
// wire format ([]byte). The fileDescriptors will include fd and all the // wire format ([]byte). The fileDescriptors will include fd and all the
// transitive dependencies of fd with names not in sentFileDescriptors. // transitive dependencies of fd with names not in sentFileDescriptors.
func fileDescWithDependencies(fd *dpb.FileDescriptorProto, sentFileDescriptors map[string]bool) ([][]byte, error) { func (s *serverReflectionServer) fileDescWithDependencies(fd protoreflect.FileDescriptor, sentFileDescriptors map[string]bool) ([][]byte, error) {
r := [][]byte{} var r [][]byte
queue := []*dpb.FileDescriptorProto{fd} queue := []protoreflect.FileDescriptor{fd}
for len(queue) > 0 { for len(queue) > 0 {
currentfd := queue[0] currentfd := queue[0]
queue = queue[1:] queue = queue[1:]
if sent := sentFileDescriptors[currentfd.GetName()]; len(r) == 0 || !sent { if sent := sentFileDescriptors[currentfd.Path()]; len(r) == 0 || !sent {
sentFileDescriptors[currentfd.GetName()] = true sentFileDescriptors[currentfd.Path()] = true
currentfdEncoded, err := proto.Marshal(currentfd) fdProto := protodesc.ToFileDescriptorProto(currentfd)
currentfdEncoded, err := proto.Marshal(fdProto)
if err != nil { if err != nil {
return nil, err return nil, err
} }
r = append(r, currentfdEncoded) r = append(r, currentfdEncoded)
} }
for _, dep := range currentfd.Dependency { for i := 0; i < currentfd.Imports().Len(); i++ {
fdenc := proto.FileDescriptor(dep) queue = append(queue, currentfd.Imports().Get(i))
fdDep, err := decodeFileDesc(fdenc)
if err != nil {
continue
}
queue = append(queue, fdDep)
} }
} }
return r, nil return r, nil
} }
// fileDescEncodingByFilename finds the file descriptor for given filename,
// finds all of its previously unsent transitive dependencies, does marshalling
// on them, and returns the marshalled result.
func (s *serverReflectionServer) fileDescEncodingByFilename(name string, sentFileDescriptors map[string]bool) ([][]byte, error) {
enc := proto.FileDescriptor(name)
if enc == nil {
return nil, fmt.Errorf("unknown file: %v", name)
}
fd, err := decodeFileDesc(enc)
if err != nil {
return nil, err
}
return fileDescWithDependencies(fd, sentFileDescriptors)
}
// parseMetadata finds the file descriptor bytes specified meta.
// For SupportPackageIsVersion4, m is the name of the proto file, we
// call proto.FileDescriptor to get the byte slice.
// For SupportPackageIsVersion3, m is a byte slice itself.
func parseMetadata(meta interface{}) ([]byte, bool) {
// Check if meta is the file name.
if fileNameForMeta, ok := meta.(string); ok {
return proto.FileDescriptor(fileNameForMeta), true
}
// Check if meta is the byte slice.
if enc, ok := meta.([]byte); ok {
return enc, true
}
return nil, false
}
// fileDescEncodingContainingSymbol finds the file descriptor containing the // fileDescEncodingContainingSymbol finds the file descriptor containing the
// given symbol, finds all of its previously unsent transitive dependencies, // given symbol, finds all of its previously unsent transitive dependencies,
// does marshalling on them, and returns the marshalled result. The given symbol // does marshalling on them, and returns the marshalled result. The given symbol
// can be a type, a service or a method. // can be a type, a service or a method.
func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) { func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) {
_, symbols := s.getSymbols() d, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name))
fd := symbols[name] if err != nil {
if fd == nil { return nil, err
// Check if it's a type name that was not present in the
// transitive dependencies of the registered services.
if st, err := typeForName(name); err == nil {
fd, err = s.fileDescForType(st)
if err != nil {
return nil, err
}
}
} }
return s.fileDescWithDependencies(d.ParentFile(), sentFileDescriptors)
if fd == nil {
return nil, fmt.Errorf("unknown symbol: %v", name)
}
return fileDescWithDependencies(fd, sentFileDescriptors)
} }
// fileDescEncodingContainingExtension finds the file descriptor containing // fileDescEncodingContainingExtension finds the file descriptor containing
// given extension, finds all of its previously unsent transitive dependencies, // given extension, finds all of its previously unsent transitive dependencies,
// does marshalling on them, and returns the marshalled result. // does marshalling on them, and returns the marshalled result.
func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) { func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) {
st, err := typeForName(typeName) xt, err := s.extResolver.FindExtensionByNumber(protoreflect.FullName(typeName), protoreflect.FieldNumber(extNum))
if err != nil { if err != nil {
return nil, err return nil, err
} }
fd, err := fileDescContainingExtension(st, extNum) return s.fileDescWithDependencies(xt.TypeDescriptor().ParentFile(), sentFileDescriptors)
if err != nil {
return nil, err
}
return fileDescWithDependencies(fd, sentFileDescriptors)
} }
// allExtensionNumbersForTypeName returns all extension numbers for the given type. // allExtensionNumbersForTypeName returns all extension numbers for the given type.
func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) { func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) {
st, err := typeForName(name) var numbers []int32
if err != nil { s.extResolver.RangeExtensionsByMessage(protoreflect.FullName(name), func(xt protoreflect.ExtensionType) bool {
return nil, err numbers = append(numbers, int32(xt.TypeDescriptor().Number()))
return true
})
sort.Slice(numbers, func(i, j int) bool {
return numbers[i] < numbers[j]
})
if len(numbers) == 0 {
// maybe return an error if given type name is not known
if _, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name)); err != nil {
return nil, err
}
} }
extNums, err := s.allExtensionNumbersForType(st) return numbers, nil
if err != nil { }
return nil, err
// listServices returns the names of services this server exposes.
func (s *serverReflectionServer) listServices() []*rpb.ServiceResponse {
serviceInfo := s.s.GetServiceInfo()
resp := make([]*rpb.ServiceResponse, 0, len(serviceInfo))
for svc := range serviceInfo {
resp = append(resp, &rpb.ServiceResponse{Name: svc})
} }
return extNums, nil sort.Slice(resp, func(i, j int) bool {
return resp[i].Name < resp[j].Name
})
return resp
} }
// ServerReflectionInfo is the reflection service handler. // ServerReflectionInfo is the reflection service handler.
@@ -412,7 +243,11 @@ func (s *serverReflectionServer) ServerReflectionInfo(stream rpb.ServerReflectio
} }
switch req := in.MessageRequest.(type) { switch req := in.MessageRequest.(type) {
case *rpb.ServerReflectionRequest_FileByFilename: case *rpb.ServerReflectionRequest_FileByFilename:
b, err := s.fileDescEncodingByFilename(req.FileByFilename, sentFileDescriptors) var b [][]byte
fd, err := s.descResolver.FindFileByPath(req.FileByFilename)
if err == nil {
b, err = s.fileDescWithDependencies(fd, sentFileDescriptors)
}
if err != nil { if err != nil {
out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{ out.MessageResponse = &rpb.ServerReflectionResponse_ErrorResponse{
ErrorResponse: &rpb.ErrorResponse{ ErrorResponse: &rpb.ErrorResponse{
@@ -473,16 +308,9 @@ func (s *serverReflectionServer) ServerReflectionInfo(stream rpb.ServerReflectio
} }
} }
case *rpb.ServerReflectionRequest_ListServices: case *rpb.ServerReflectionRequest_ListServices:
svcNames, _ := s.getSymbols()
serviceResponses := make([]*rpb.ServiceResponse, len(svcNames))
for i, n := range svcNames {
serviceResponses[i] = &rpb.ServiceResponse{
Name: n,
}
}
out.MessageResponse = &rpb.ServerReflectionResponse_ListServicesResponse{ out.MessageResponse = &rpb.ServerReflectionResponse_ListServicesResponse{
ListServicesResponse: &rpb.ListServiceResponse{ ListServicesResponse: &rpb.ListServiceResponse{
Service: serviceResponses, Service: s.listServices(),
}, },
} }
default: default:

View File

@@ -27,9 +27,9 @@ export PATH=${GOBIN}:${PATH}
mkdir -p ${GOBIN} mkdir -p ${GOBIN}
echo "remove existing generated files" echo "remove existing generated files"
# grpc_testingv3/testv3.pb.go is not re-generated because it was # grpc_testing_not_regenerate/*.pb.go is not re-generated,
# intentionally generated by an older version of protoc-gen-go. # see grpc_testing_not_regenerate/README.md for details.
rm -f $(find . -name '*.pb.go' | grep -v 'grpc_testingv3/testv3.pb.go') rm -f $(find . -name '*.pb.go' | grep -v 'grpc_testing_not_regenerate')
echo "go install google.golang.org/protobuf/cmd/protoc-gen-go" echo "go install google.golang.org/protobuf/cmd/protoc-gen-go"
(cd test/tools && go install google.golang.org/protobuf/cmd/protoc-gen-go) (cd test/tools && go install google.golang.org/protobuf/cmd/protoc-gen-go)
@@ -76,7 +76,21 @@ SOURCES=(
# These options of the form 'Mfoo.proto=bar' instruct the codegen to use an # These options of the form 'Mfoo.proto=bar' instruct the codegen to use an
# import path of 'bar' in the generated code when 'foo.proto' is imported in # import path of 'bar' in the generated code when 'foo.proto' is imported in
# one of the sources. # one of the sources.
OPTS=Mgrpc/service_config/service_config.proto=/internal/proto/grpc_service_config,Mgrpc/core/stats.proto=google.golang.org/grpc/interop/grpc_testing/core #
# Note that the protos listed here are all for testing purposes. All protos to
# be used externally should have a go_package option (and they don't need to be
# listed here).
OPTS=Mgrpc/service_config/service_config.proto=/internal/proto/grpc_service_config,\
Mgrpc/core/stats.proto=google.golang.org/grpc/interop/grpc_testing/core,\
Mgrpc/testing/benchmark_service.proto=google.golang.org/grpc/interop/grpc_testing,\
Mgrpc/testing/stats.proto=google.golang.org/grpc/interop/grpc_testing,\
Mgrpc/testing/report_qps_scenario_service.proto=google.golang.org/grpc/interop/grpc_testing,\
Mgrpc/testing/messages.proto=google.golang.org/grpc/interop/grpc_testing,\
Mgrpc/testing/worker_service.proto=google.golang.org/grpc/interop/grpc_testing,\
Mgrpc/testing/control.proto=google.golang.org/grpc/interop/grpc_testing,\
Mgrpc/testing/test.proto=google.golang.org/grpc/interop/grpc_testing,\
Mgrpc/testing/payloads.proto=google.golang.org/grpc/interop/grpc_testing,\
Mgrpc/testing/empty.proto=google.golang.org/grpc/interop/grpc_testing
for src in ${SOURCES[@]}; do for src in ${SOURCES[@]}; do
echo "protoc ${src}" echo "protoc ${src}"
@@ -85,7 +99,6 @@ for src in ${SOURCES[@]}; do
-I${WORKDIR}/grpc-proto \ -I${WORKDIR}/grpc-proto \
-I${WORKDIR}/googleapis \ -I${WORKDIR}/googleapis \
-I${WORKDIR}/protobuf/src \ -I${WORKDIR}/protobuf/src \
-I${WORKDIR}/istio \
${src} ${src}
done done
@@ -96,18 +109,17 @@ for src in ${LEGACY_SOURCES[@]}; do
-I${WORKDIR}/grpc-proto \ -I${WORKDIR}/grpc-proto \
-I${WORKDIR}/googleapis \ -I${WORKDIR}/googleapis \
-I${WORKDIR}/protobuf/src \ -I${WORKDIR}/protobuf/src \
-I${WORKDIR}/istio \
${src} ${src}
done done
# The go_package option in grpc/lookup/v1/rls.proto doesn't match the # The go_package option in grpc/lookup/v1/rls.proto doesn't match the
# current location. Move it into the right place. # current location. Move it into the right place.
mkdir -p ${WORKDIR}/out/google.golang.org/grpc/balancer/rls/internal/proto/grpc_lookup_v1 mkdir -p ${WORKDIR}/out/google.golang.org/grpc/internal/proto/grpc_lookup_v1
mv ${WORKDIR}/out/google.golang.org/grpc/lookup/grpc_lookup_v1/* ${WORKDIR}/out/google.golang.org/grpc/balancer/rls/internal/proto/grpc_lookup_v1 mv ${WORKDIR}/out/google.golang.org/grpc/lookup/grpc_lookup_v1/* ${WORKDIR}/out/google.golang.org/grpc/internal/proto/grpc_lookup_v1
# grpc_testingv3/testv3.pb.go is not re-generated because it was # grpc_testing_not_regenerate/*.pb.go are not re-generated,
# intentionally generated by an older version of protoc-gen-go. # see grpc_testing_not_regenerate/README.md for details.
rm ${WORKDIR}/out/google.golang.org/grpc/reflection/grpc_testingv3/*.pb.go rm ${WORKDIR}/out/google.golang.org/grpc/reflection/grpc_testing_not_regenerate/*.pb.go
# grpc/service_config/service_config.proto does not have a go_package option. # grpc/service_config/service_config.proto does not have a go_package option.
mv ${WORKDIR}/out/grpc/service_config/service_config.pb.go internal/proto/grpc_service_config mv ${WORKDIR}/out/grpc/service_config/service_config.pb.go internal/proto/grpc_service_config

109
vendor/google.golang.org/grpc/resolver/map.go generated vendored Normal file
View File

@@ -0,0 +1,109 @@
/*
*
* Copyright 2021 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package resolver
type addressMapEntry struct {
addr Address
value interface{}
}
// AddressMap is a map of addresses to arbitrary values taking into account
// Attributes. BalancerAttributes are ignored, as are Metadata and Type.
// Multiple accesses may not be performed concurrently. Must be created via
// NewAddressMap; do not construct directly.
type AddressMap struct {
m map[string]addressMapEntryList
}
type addressMapEntryList []*addressMapEntry
// NewAddressMap creates a new AddressMap.
func NewAddressMap() *AddressMap {
return &AddressMap{m: make(map[string]addressMapEntryList)}
}
// find returns the index of addr in the addressMapEntry slice, or -1 if not
// present.
func (l addressMapEntryList) find(addr Address) int {
if len(l) == 0 {
return -1
}
for i, entry := range l {
if entry.addr.ServerName == addr.ServerName &&
entry.addr.Attributes.Equal(addr.Attributes) {
return i
}
}
return -1
}
// Get returns the value for the address in the map, if present.
func (a *AddressMap) Get(addr Address) (value interface{}, ok bool) {
entryList := a.m[addr.Addr]
if entry := entryList.find(addr); entry != -1 {
return entryList[entry].value, true
}
return nil, false
}
// Set updates or adds the value to the address in the map.
func (a *AddressMap) Set(addr Address, value interface{}) {
entryList := a.m[addr.Addr]
if entry := entryList.find(addr); entry != -1 {
a.m[addr.Addr][entry].value = value
return
}
a.m[addr.Addr] = append(a.m[addr.Addr], &addressMapEntry{addr: addr, value: value})
}
// Delete removes addr from the map.
func (a *AddressMap) Delete(addr Address) {
entryList := a.m[addr.Addr]
entry := entryList.find(addr)
if entry == -1 {
return
}
if len(entryList) == 1 {
entryList = nil
} else {
copy(entryList[entry:], entryList[entry+1:])
entryList = entryList[:len(entryList)-1]
}
a.m[addr.Addr] = entryList
}
// Len returns the number of entries in the map.
func (a *AddressMap) Len() int {
ret := 0
for _, entryList := range a.m {
ret += len(entryList)
}
return ret
}
// Keys returns a slice of all current map keys.
func (a *AddressMap) Keys() []Address {
ret := make([]Address, 0, a.Len())
for _, entryList := range a.m {
for _, entry := range entryList {
ret = append(ret, entry.addr)
}
}
return ret
}

View File

@@ -23,9 +23,11 @@ package resolver
import ( import (
"context" "context"
"net" "net"
"net/url"
"google.golang.org/grpc/attributes" "google.golang.org/grpc/attributes"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal/pretty"
"google.golang.org/grpc/serviceconfig" "google.golang.org/grpc/serviceconfig"
) )
@@ -116,9 +118,14 @@ type Address struct {
ServerName string ServerName string
// Attributes contains arbitrary data about this address intended for // Attributes contains arbitrary data about this address intended for
// consumption by the load balancing policy. // consumption by the SubConn.
Attributes *attributes.Attributes Attributes *attributes.Attributes
// BalancerAttributes contains arbitrary data about this address intended
// for consumption by the LB policy. These attribes do not affect SubConn
// creation, connection establishment, handshaking, etc.
BalancerAttributes *attributes.Attributes
// Type is the type of this address. // Type is the type of this address.
// //
// Deprecated: use Attributes instead. // Deprecated: use Attributes instead.
@@ -131,6 +138,20 @@ type Address struct {
Metadata interface{} Metadata interface{}
} }
// Equal returns whether a and o are identical. Metadata is compared directly,
// not with any recursive introspection.
func (a Address) Equal(o Address) bool {
return a.Addr == o.Addr && a.ServerName == o.ServerName &&
a.Attributes.Equal(o.Attributes) &&
a.BalancerAttributes.Equal(o.BalancerAttributes) &&
a.Type == o.Type && a.Metadata == o.Metadata
}
// String returns JSON formatted string representation of the address.
func (a Address) String() string {
return pretty.ToJSON(a)
}
// BuildOptions includes additional information for the builder to create // BuildOptions includes additional information for the builder to create
// the resolver. // the resolver.
type BuildOptions struct { type BuildOptions struct {
@@ -204,25 +225,36 @@ type ClientConn interface {
// Target represents a target for gRPC, as specified in: // Target represents a target for gRPC, as specified in:
// https://github.com/grpc/grpc/blob/master/doc/naming.md. // https://github.com/grpc/grpc/blob/master/doc/naming.md.
// It is parsed from the target string that gets passed into Dial or DialContext by the user. And // It is parsed from the target string that gets passed into Dial or DialContext
// grpc passes it to the resolver and the balancer. // by the user. And gRPC passes it to the resolver and the balancer.
// //
// If the target follows the naming spec, and the parsed scheme is registered with grpc, we will // If the target follows the naming spec, and the parsed scheme is registered
// parse the target string according to the spec. e.g. "dns://some_authority/foo.bar" will be parsed // with gRPC, we will parse the target string according to the spec. If the
// into &Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"} // target does not contain a scheme or if the parsed scheme is not registered
// (i.e. no corresponding resolver available to resolve the endpoint), we will
// apply the default scheme, and will attempt to reparse it.
// //
// If the target does not contain a scheme, we will apply the default scheme, and set the Target to // Examples:
// be the full target string. e.g. "foo.bar" will be parsed into
// &Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "foo.bar"}.
// //
// If the parsed scheme is not registered (i.e. no corresponding resolver available to resolve the // - "dns://some_authority/foo.bar"
// endpoint), we set the Scheme to be the default scheme, and set the Endpoint to be the full target // Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"}
// string. e.g. target string "unknown_scheme://authority/endpoint" will be parsed into // - "foo.bar"
// &Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "unknown_scheme://authority/endpoint"}. // Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "foo.bar"}
// - "unknown_scheme://authority/endpoint"
// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "unknown_scheme://authority/endpoint"}
type Target struct { type Target struct {
Scheme string // Deprecated: use URL.Scheme instead.
Scheme string
// Deprecated: use URL.Host instead.
Authority string Authority string
Endpoint string // Deprecated: use URL.Path or URL.Opaque instead. The latter is set when
// the former is empty.
Endpoint string
// URL contains the parsed dial target with an optional default scheme added
// to it if the original dial target contained no scheme or contained an
// unregistered scheme. Any query params specified in the original dial
// target can be accessed from here.
URL url.URL
} }
// Builder creates a resolver that will be used to watch name resolution updates. // Builder creates a resolver that will be used to watch name resolution updates.

View File

@@ -19,7 +19,6 @@
package grpc package grpc
import ( import (
"fmt"
"strings" "strings"
"sync" "sync"
@@ -27,6 +26,7 @@ import (
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/channelz"
"google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpcsync"
"google.golang.org/grpc/internal/pretty"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
"google.golang.org/grpc/serviceconfig" "google.golang.org/grpc/serviceconfig"
) )
@@ -97,10 +97,7 @@ func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
if ccr.done.HasFired() { if ccr.done.HasFired() {
return nil return nil
} }
channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: sending update to cc: %v", s) ccr.addChannelzTraceEvent(s)
if channelz.IsOn() {
ccr.addChannelzTraceEvent(s)
}
ccr.curState = s ccr.curState = s
if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState { if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState {
return balancer.ErrBadResolverState return balancer.ErrBadResolverState
@@ -125,10 +122,7 @@ func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
if ccr.done.HasFired() { if ccr.done.HasFired() {
return return
} }
channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: sending new addresses to cc: %v", addrs) ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
if channelz.IsOn() {
ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
}
ccr.curState.Addresses = addrs ccr.curState.Addresses = addrs
ccr.cc.updateResolverState(ccr.curState, nil) ccr.cc.updateResolverState(ccr.curState, nil)
} }
@@ -141,7 +135,7 @@ func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
if ccr.done.HasFired() { if ccr.done.HasFired() {
return return
} }
channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: got new service config: %v", sc) channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: got new service config: %s", sc)
if ccr.cc.dopts.disableServiceConfig { if ccr.cc.dopts.disableServiceConfig {
channelz.Info(logger, ccr.cc.channelzID, "Service config lookups disabled; ignoring config") channelz.Info(logger, ccr.cc.channelzID, "Service config lookups disabled; ignoring config")
return return
@@ -151,9 +145,7 @@ func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err) channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err)
return return
} }
if channelz.IsOn() { ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr})
ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr})
}
ccr.curState.ServiceConfig = scpr ccr.curState.ServiceConfig = scpr
ccr.cc.updateResolverState(ccr.curState, nil) ccr.cc.updateResolverState(ccr.curState, nil)
} }
@@ -180,8 +172,5 @@ func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) {
} else if len(ccr.curState.Addresses) == 0 && len(s.Addresses) > 0 { } else if len(ccr.curState.Addresses) == 0 && len(s.Addresses) > 0 {
updates = append(updates, "resolver returned new addresses") updates = append(updates, "resolver returned new addresses")
} }
channelz.AddTraceEvent(logger, ccr.cc.channelzID, 0, &channelz.TraceEventDesc{ channelz.Infof(logger, ccr.cc.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; "))
Desc: fmt.Sprintf("Resolver state updated: %+v (%v)", s, strings.Join(updates, "; ")),
Severity: channelz.CtInfo,
})
} }

View File

@@ -712,13 +712,11 @@ func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxRecei
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
} }
} else { if size > maxReceiveMessageSize {
size = len(d) // TODO: Revisit the error code. Currently keep it consistent with java
} // implementation.
if size > maxReceiveMessageSize { return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize)
// TODO: Revisit the error code. Currently keep it consistent with java }
// implementation.
return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", size, maxReceiveMessageSize)
} }
return d, nil return d, nil
} }

View File

@@ -134,7 +134,7 @@ type Server struct {
channelzRemoveOnce sync.Once channelzRemoveOnce sync.Once
serveWG sync.WaitGroup // counts active Serve goroutines for GracefulStop serveWG sync.WaitGroup // counts active Serve goroutines for GracefulStop
channelzID int64 // channelz unique identification number channelzID *channelz.Identifier
czData *channelzData czData *channelzData
serverWorkerChannels []chan *serverWorkerData serverWorkerChannels []chan *serverWorkerData
@@ -584,9 +584,8 @@ func NewServer(opt ...ServerOption) *Server {
s.initServerWorkers() s.initServerWorkers()
} }
if channelz.IsOn() { s.channelzID = channelz.RegisterServer(&channelzServer{s}, "")
s.channelzID = channelz.RegisterServer(&channelzServer{s}, "") channelz.Info(logger, s.channelzID, "Server created")
}
return s return s
} }
@@ -710,16 +709,9 @@ func (s *Server) GetServiceInfo() map[string]ServiceInfo {
// the server being stopped. // the server being stopped.
var ErrServerStopped = errors.New("grpc: the server has been stopped") var ErrServerStopped = errors.New("grpc: the server has been stopped")
func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
if s.opts.creds == nil {
return rawConn, nil, nil
}
return s.opts.creds.ServerHandshake(rawConn)
}
type listenSocket struct { type listenSocket struct {
net.Listener net.Listener
channelzID int64 channelzID *channelz.Identifier
} }
func (l *listenSocket) ChannelzMetric() *channelz.SocketInternalMetric { func (l *listenSocket) ChannelzMetric() *channelz.SocketInternalMetric {
@@ -731,9 +723,8 @@ func (l *listenSocket) ChannelzMetric() *channelz.SocketInternalMetric {
func (l *listenSocket) Close() error { func (l *listenSocket) Close() error {
err := l.Listener.Close() err := l.Listener.Close()
if channelz.IsOn() { channelz.RemoveEntry(l.channelzID)
channelz.RemoveEntry(l.channelzID) channelz.Info(logger, l.channelzID, "ListenSocket deleted")
}
return err return err
} }
@@ -766,11 +757,6 @@ func (s *Server) Serve(lis net.Listener) error {
ls := &listenSocket{Listener: lis} ls := &listenSocket{Listener: lis}
s.lis[ls] = true s.lis[ls] = true
if channelz.IsOn() {
ls.channelzID = channelz.RegisterListenSocket(ls, s.channelzID, lis.Addr().String())
}
s.mu.Unlock()
defer func() { defer func() {
s.mu.Lock() s.mu.Lock()
if s.lis != nil && s.lis[ls] { if s.lis != nil && s.lis[ls] {
@@ -780,8 +766,16 @@ func (s *Server) Serve(lis net.Listener) error {
s.mu.Unlock() s.mu.Unlock()
}() }()
var tempDelay time.Duration // how long to sleep on accept failure var err error
ls.channelzID, err = channelz.RegisterListenSocket(ls, s.channelzID, lis.Addr().String())
if err != nil {
s.mu.Unlock()
return err
}
s.mu.Unlock()
channelz.Info(logger, ls.channelzID, "ListenSocket created")
var tempDelay time.Duration // how long to sleep on accept failure
for { for {
rawConn, err := lis.Accept() rawConn, err := lis.Accept()
if err != nil { if err != nil {
@@ -839,35 +833,14 @@ func (s *Server) handleRawConn(lisAddr string, rawConn net.Conn) {
return return
} }
rawConn.SetDeadline(time.Now().Add(s.opts.connectionTimeout)) rawConn.SetDeadline(time.Now().Add(s.opts.connectionTimeout))
conn, authInfo, err := s.useTransportAuthenticator(rawConn)
if err != nil {
// ErrConnDispatched means that the connection was dispatched away from
// gRPC; those connections should be left open.
if err != credentials.ErrConnDispatched {
// In deployments where a gRPC server runs behind a cloud load
// balancer which performs regular TCP level health checks, the
// connection is closed immediately by the latter. Skipping the
// error here will help reduce log clutter.
if err != io.EOF {
s.mu.Lock()
s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err)
s.mu.Unlock()
channelz.Warningf(logger, s.channelzID, "grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err)
}
rawConn.Close()
}
rawConn.SetDeadline(time.Time{})
return
}
// Finish handshaking (HTTP2) // Finish handshaking (HTTP2)
st := s.newHTTP2Transport(conn, authInfo) st := s.newHTTP2Transport(rawConn)
rawConn.SetDeadline(time.Time{})
if st == nil { if st == nil {
conn.Close()
return return
} }
rawConn.SetDeadline(time.Time{})
if !s.addConn(lisAddr, st) { if !s.addConn(lisAddr, st) {
return return
} }
@@ -888,10 +861,11 @@ func (s *Server) drainServerTransports(addr string) {
// newHTTP2Transport sets up a http/2 transport (using the // newHTTP2Transport sets up a http/2 transport (using the
// gRPC http2 server transport in transport/http2_server.go). // gRPC http2 server transport in transport/http2_server.go).
func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) transport.ServerTransport { func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport {
config := &transport.ServerConfig{ config := &transport.ServerConfig{
MaxStreams: s.opts.maxConcurrentStreams, MaxStreams: s.opts.maxConcurrentStreams,
AuthInfo: authInfo, ConnectionTimeout: s.opts.connectionTimeout,
Credentials: s.opts.creds,
InTapHandle: s.opts.inTapHandle, InTapHandle: s.opts.inTapHandle,
StatsHandler: s.opts.statsHandler, StatsHandler: s.opts.statsHandler,
KeepaliveParams: s.opts.keepaliveParams, KeepaliveParams: s.opts.keepaliveParams,
@@ -909,8 +883,15 @@ func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) tr
s.mu.Lock() s.mu.Lock()
s.errorf("NewServerTransport(%q) failed: %v", c.RemoteAddr(), err) s.errorf("NewServerTransport(%q) failed: %v", c.RemoteAddr(), err)
s.mu.Unlock() s.mu.Unlock()
c.Close() // ErrConnDispatched means that the connection was dispatched away from
channelz.Warning(logger, s.channelzID, "grpc: Server.Serve failed to create ServerTransport: ", err) // gRPC; those connections should be left open.
if err != credentials.ErrConnDispatched {
// Don't log on ErrConnDispatched and io.EOF to prevent log spam.
if err != io.EOF {
channelz.Warning(logger, s.channelzID, "grpc: Server.Serve failed to create ServerTransport: ", err)
}
c.Close()
}
return nil return nil
} }
@@ -1124,16 +1105,21 @@ func chainUnaryServerInterceptors(s *Server) {
func chainUnaryInterceptors(interceptors []UnaryServerInterceptor) UnaryServerInterceptor { func chainUnaryInterceptors(interceptors []UnaryServerInterceptor) UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (interface{}, error) { return func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (interface{}, error) {
var i int // the struct ensures the variables are allocated together, rather than separately, since we
var next UnaryHandler // know they should be garbage collected together. This saves 1 allocation and decreases
next = func(ctx context.Context, req interface{}) (interface{}, error) { // time/call by about 10% on the microbenchmark.
if i == len(interceptors)-1 { var state struct {
return interceptors[i](ctx, req, info, handler) i int
} next UnaryHandler
i++
return interceptors[i-1](ctx, req, info, next)
} }
return next(ctx, req) state.next = func(ctx context.Context, req interface{}) (interface{}, error) {
if state.i == len(interceptors)-1 {
return interceptors[state.i](ctx, req, info, handler)
}
state.i++
return interceptors[state.i-1](ctx, req, info, state.next)
}
return state.next(ctx, req)
} }
} }
@@ -1298,9 +1284,10 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
if appErr != nil { if appErr != nil {
appStatus, ok := status.FromError(appErr) appStatus, ok := status.FromError(appErr)
if !ok { if !ok {
// Convert appErr if it is not a grpc status error. // Convert non-status application error to a status error with code
appErr = status.Error(codes.Unknown, appErr.Error()) // Unknown, but handle context errors specifically.
appStatus, _ = status.FromError(appErr) appStatus = status.FromContextError(appErr)
appErr = appStatus.Err()
} }
if trInfo != nil { if trInfo != nil {
trInfo.tr.LazyLog(stringer(appStatus.Message()), true) trInfo.tr.LazyLog(stringer(appStatus.Message()), true)
@@ -1409,16 +1396,21 @@ func chainStreamServerInterceptors(s *Server) {
func chainStreamInterceptors(interceptors []StreamServerInterceptor) StreamServerInterceptor { func chainStreamInterceptors(interceptors []StreamServerInterceptor) StreamServerInterceptor {
return func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error { return func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error {
var i int // the struct ensures the variables are allocated together, rather than separately, since we
var next StreamHandler // know they should be garbage collected together. This saves 1 allocation and decreases
next = func(srv interface{}, ss ServerStream) error { // time/call by about 10% on the microbenchmark.
if i == len(interceptors)-1 { var state struct {
return interceptors[i](srv, ss, info, handler) i int
} next StreamHandler
i++
return interceptors[i-1](srv, ss, info, next)
} }
return next(srv, ss) state.next = func(srv interface{}, ss ServerStream) error {
if state.i == len(interceptors)-1 {
return interceptors[state.i](srv, ss, info, handler)
}
state.i++
return interceptors[state.i-1](srv, ss, info, state.next)
}
return state.next(srv, ss)
} }
} }
@@ -1559,7 +1551,9 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
if appErr != nil { if appErr != nil {
appStatus, ok := status.FromError(appErr) appStatus, ok := status.FromError(appErr)
if !ok { if !ok {
appStatus = status.New(codes.Unknown, appErr.Error()) // Convert non-status application error to a status error with code
// Unknown, but handle context errors specifically.
appStatus = status.FromContextError(appErr)
appErr = appStatus.Err() appErr = appStatus.Err()
} }
if trInfo != nil { if trInfo != nil {
@@ -1716,11 +1710,7 @@ func (s *Server) Stop() {
s.done.Fire() s.done.Fire()
}() }()
s.channelzRemoveOnce.Do(func() { s.channelzRemoveOnce.Do(func() { channelz.RemoveEntry(s.channelzID) })
if channelz.IsOn() {
channelz.RemoveEntry(s.channelzID)
}
})
s.mu.Lock() s.mu.Lock()
listeners := s.lis listeners := s.lis
@@ -1758,11 +1748,7 @@ func (s *Server) GracefulStop() {
s.quit.Fire() s.quit.Fire()
defer s.done.Fire() defer s.done.Fire()
s.channelzRemoveOnce.Do(func() { s.channelzRemoveOnce.Do(func() { channelz.RemoveEntry(s.channelzID) })
if channelz.IsOn() {
channelz.RemoveEntry(s.channelzID)
}
})
s.mu.Lock() s.mu.Lock()
if s.conns == nil { if s.conns == nil {
s.mu.Unlock() s.mu.Unlock()
@@ -1815,12 +1801,26 @@ func (s *Server) getCodec(contentSubtype string) baseCodec {
return codec return codec
} }
// SetHeader sets the header metadata. // SetHeader sets the header metadata to be sent from the server to the client.
// When called multiple times, all the provided metadata will be merged. // The context provided must be the context passed to the server's handler.
// All the metadata will be sent out when one of the following happens: //
// - grpc.SendHeader() is called; // Streaming RPCs should prefer the SetHeader method of the ServerStream.
// - The first response is sent out; //
// - An RPC status is sent out (error or success). // When called multiple times, all the provided metadata will be merged. All
// the metadata will be sent out when one of the following happens:
//
// - grpc.SendHeader is called, or for streaming handlers, stream.SendHeader.
// - The first response message is sent. For unary handlers, this occurs when
// the handler returns; for streaming handlers, this can happen when stream's
// SendMsg method is called.
// - An RPC status is sent out (error or success). This occurs when the handler
// returns.
//
// SetHeader will fail if called after any of the events above.
//
// The error returned is compatible with the status package. However, the
// status code will often not match the RPC status as seen by the client
// application, and therefore, should not be relied upon for this purpose.
func SetHeader(ctx context.Context, md metadata.MD) error { func SetHeader(ctx context.Context, md metadata.MD) error {
if md.Len() == 0 { if md.Len() == 0 {
return nil return nil
@@ -1832,8 +1832,14 @@ func SetHeader(ctx context.Context, md metadata.MD) error {
return stream.SetHeader(md) return stream.SetHeader(md)
} }
// SendHeader sends header metadata. It may be called at most once. // SendHeader sends header metadata. It may be called at most once, and may not
// The provided md and headers set by SetHeader() will be sent. // be called after any event that causes headers to be sent (see SetHeader for
// a complete list). The provided md and headers set by SetHeader() will be
// sent.
//
// The error returned is compatible with the status package. However, the
// status code will often not match the RPC status as seen by the client
// application, and therefore, should not be relied upon for this purpose.
func SendHeader(ctx context.Context, md metadata.MD) error { func SendHeader(ctx context.Context, md metadata.MD) error {
stream := ServerTransportStreamFromContext(ctx) stream := ServerTransportStreamFromContext(ctx)
if stream == nil { if stream == nil {
@@ -1847,6 +1853,10 @@ func SendHeader(ctx context.Context, md metadata.MD) error {
// SetTrailer sets the trailer metadata that will be sent when an RPC returns. // SetTrailer sets the trailer metadata that will be sent when an RPC returns.
// When called more than once, all the provided metadata will be merged. // When called more than once, all the provided metadata will be merged.
//
// The error returned is compatible with the status package. However, the
// status code will often not match the RPC status as seen by the client
// application, and therefore, should not be relied upon for this purpose.
func SetTrailer(ctx context.Context, md metadata.MD) error { func SetTrailer(ctx context.Context, md metadata.MD) error {
if md.Len() == 0 { if md.Len() == 0 {
return nil return nil

View File

@@ -218,7 +218,7 @@ type jsonSC struct {
} }
func init() { func init() {
internal.ParseServiceConfigForTesting = parseServiceConfig internal.ParseServiceConfig = parseServiceConfig
} }
func parseServiceConfig(js string) *serviceconfig.ParseResult { func parseServiceConfig(js string) *serviceconfig.ParseResult {
if len(js) == 0 { if len(js) == 0 {
@@ -381,6 +381,9 @@ func init() {
// //
// If any of them is NOT *ServiceConfig, return false. // If any of them is NOT *ServiceConfig, return false.
func equalServiceConfig(a, b serviceconfig.Config) bool { func equalServiceConfig(a, b serviceconfig.Config) bool {
if a == nil && b == nil {
return true
}
aa, ok := a.(*ServiceConfig) aa, ok := a.(*ServiceConfig)
if !ok { if !ok {
return false return false

Some files were not shown because too many files have changed in this diff Show More