vendor containers/common@main
Pull in fixes for local image lookups. Fixes: #10835 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
parent
955c1d2bfe
commit
7eb9ed9758
8
go.mod
8
go.mod
|
|
@ -12,7 +12,7 @@ require (
|
||||||
github.com/containernetworking/cni v0.8.1
|
github.com/containernetworking/cni v0.8.1
|
||||||
github.com/containernetworking/plugins v0.9.1
|
github.com/containernetworking/plugins v0.9.1
|
||||||
github.com/containers/buildah v1.21.1-0.20210628174543-eadb10a12336
|
github.com/containers/buildah v1.21.1-0.20210628174543-eadb10a12336
|
||||||
github.com/containers/common v0.40.2-0.20210630092122-7482cf851dcc
|
github.com/containers/common v0.40.2-0.20210702074932-9d34b37ba77e
|
||||||
github.com/containers/conmon v2.0.20+incompatible
|
github.com/containers/conmon v2.0.20+incompatible
|
||||||
github.com/containers/image/v5 v5.13.2
|
github.com/containers/image/v5 v5.13.2
|
||||||
github.com/containers/ocicrypt v1.1.2
|
github.com/containers/ocicrypt v1.1.2
|
||||||
|
|
@ -54,7 +54,7 @@ require (
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
github.com/pmezard/go-difflib v1.0.0
|
||||||
github.com/rootless-containers/rootlesskit v0.14.2
|
github.com/rootless-containers/rootlesskit v0.14.2
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/spf13/cobra v1.1.3
|
github.com/spf13/cobra v1.2.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
|
||||||
|
|
@ -63,9 +63,9 @@ require (
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852
|
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852
|
||||||
go.etcd.io/bbolt v1.3.6
|
go.etcd.io/bbolt v1.3.6
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644
|
golang.org/x/sys v0.0.0-20210603125802-9665404d3644
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
k8s.io/api v0.21.2
|
k8s.io/api v0.21.2
|
||||||
k8s.io/apimachinery v0.21.2
|
k8s.io/apimachinery v0.21.2
|
||||||
)
|
)
|
||||||
|
|
|
||||||
187
go.sum
187
go.sum
|
|
@ -10,18 +10,33 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T
|
||||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||||
|
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||||
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
|
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||||
|
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||||
|
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.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||||
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=
|
||||||
|
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||||
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7d2mcFdvxC9uyrdcTfvBbPLThhkDmXzg=
|
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7d2mcFdvxC9uyrdcTfvBbPLThhkDmXzg=
|
||||||
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0=
|
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0=
|
||||||
|
|
@ -76,6 +91,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/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-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||||
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
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=
|
||||||
|
|
@ -92,6 +108,7 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE
|
||||||
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
|
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
|
||||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||||
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.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
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=
|
||||||
|
|
@ -130,6 +147,8 @@ github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ
|
||||||
github.com/cilium/ebpf v0.6.1/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
github.com/cilium/ebpf v0.6.1/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9 h1:Kn0s9/APRtr5dk/83aXj97WX0+PYnJK9BO8g0Xclm0I=
|
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9 h1:Kn0s9/APRtr5dk/83aXj97WX0+PYnJK9BO8g0Xclm0I=
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9/go.mod h1:eQt66kIaJpUhCrjCtBFQGQxGLbAUl0OuuwjTH16ON4s=
|
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9/go.mod h1:eQt66kIaJpUhCrjCtBFQGQxGLbAUl0OuuwjTH16ON4s=
|
||||||
|
|
@ -221,8 +240,8 @@ github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRD
|
||||||
github.com/containers/buildah v1.21.1-0.20210628174543-eadb10a12336 h1:LAjAsDE6sxZnDoSzE384o/cRuTGGn1OMjkd9YIPT2bg=
|
github.com/containers/buildah v1.21.1-0.20210628174543-eadb10a12336 h1:LAjAsDE6sxZnDoSzE384o/cRuTGGn1OMjkd9YIPT2bg=
|
||||||
github.com/containers/buildah v1.21.1-0.20210628174543-eadb10a12336/go.mod h1:HZ2k0W/EREpNxr+AnRZQzjjBdhXLItp9yuzwAaVa6zM=
|
github.com/containers/buildah v1.21.1-0.20210628174543-eadb10a12336/go.mod h1:HZ2k0W/EREpNxr+AnRZQzjjBdhXLItp9yuzwAaVa6zM=
|
||||||
github.com/containers/common v0.40.1/go.mod h1:X4F+6vmeAWKMMTNHlOBwOnkf5TQAkQACcuNsKjfcodw=
|
github.com/containers/common v0.40.1/go.mod h1:X4F+6vmeAWKMMTNHlOBwOnkf5TQAkQACcuNsKjfcodw=
|
||||||
github.com/containers/common v0.40.2-0.20210630092122-7482cf851dcc h1:7fqEcoNUaEHmg7gIFui2BDGU8sFpEU6xDxABxhYPOPw=
|
github.com/containers/common v0.40.2-0.20210702074932-9d34b37ba77e h1:ubkW5+D74+JrEL6qFmdAQpZ2L1jdGrRYPpkgKdV2YEw=
|
||||||
github.com/containers/common v0.40.2-0.20210630092122-7482cf851dcc/go.mod h1:H3H/223r/e2uAVUdwZxuiRkWPvxynORzh5iChjFJ43o=
|
github.com/containers/common v0.40.2-0.20210702074932-9d34b37ba77e/go.mod h1:dbz5oauwVA4I/9HMe7YQUt6LWUmrYQlwQH9LQ35bm/U=
|
||||||
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
||||||
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
||||||
github.com/containers/image/v5 v5.13.2 h1:AgYunV/9d2fRkrmo23wH2MkqeHolFd6oQCkK+1PpuFA=
|
github.com/containers/image/v5 v5.13.2 h1:AgYunV/9d2fRkrmo23wH2MkqeHolFd6oQCkK+1PpuFA=
|
||||||
|
|
@ -326,6 +345,9 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT
|
||||||
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=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||||
|
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/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/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
||||||
|
|
@ -394,6 +416,9 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
|
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
|
@ -409,6 +434,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
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/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||||
|
|
@ -419,9 +445,11 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
|
|
@ -432,11 +460,19 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
||||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
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=
|
||||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/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/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-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
||||||
|
|
@ -465,6 +501,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
|
@ -495,6 +532,7 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
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/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||||
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/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
|
|
@ -543,6 +581,7 @@ github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQ
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
|
@ -556,6 +595,7 @@ github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBF
|
||||||
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||||
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.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||||
|
|
@ -602,6 +642,8 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
|
||||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
|
|
@ -707,6 +749,7 @@ github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913/go.mod h1:J6OG
|
||||||
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.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||||
|
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.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
|
@ -714,6 +757,7 @@ github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
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=
|
||||||
|
|
@ -756,6 +800,7 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rootless-containers/rootlesskit v0.14.2 h1:jmsSyNyRG0QdWc3usppt5jEy5qOheeUsIINcymPrOFg=
|
github.com/rootless-containers/rootlesskit v0.14.2 h1:jmsSyNyRG0QdWc3usppt5jEy5qOheeUsIINcymPrOFg=
|
||||||
github.com/rootless-containers/rootlesskit v0.14.2/go.mod h1:nV3TpRISvwhZQSwo0nmQQnxjCxXr3mvrMi0oASLvzcg=
|
github.com/rootless-containers/rootlesskit v0.14.2/go.mod h1:nV3TpRISvwhZQSwo0nmQQnxjCxXr3mvrMi0oASLvzcg=
|
||||||
|
|
@ -787,14 +832,18 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
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/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 v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
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.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||||
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
|
|
||||||
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.0 h1:IHGo93KUJjih0Gz449MCBDKuaWPqcKcbuUM7GXWFnlw=
|
||||||
|
github.com/spf13/cobra v1.2.0/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
|
||||||
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 v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
|
@ -803,6 +852,7 @@ 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/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=
|
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=
|
||||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||||
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
|
@ -865,9 +915,11 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
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/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.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
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/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||||
|
|
@ -877,17 +929,26 @@ go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||||
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 v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
||||||
|
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||||
|
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M=
|
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M=
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||||
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=
|
||||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
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.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||||
|
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
|
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
|
@ -897,6 +958,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
|
@ -925,6 +987,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
|
@ -933,6 +997,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
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.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-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=
|
||||||
|
|
@ -953,6 +1020,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
|
@ -965,18 +1033,27 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
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=
|
||||||
|
|
@ -984,16 +1061,25 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
|
||||||
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=
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/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-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/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=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
|
|
||||||
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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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=
|
||||||
|
|
@ -1048,11 +1134,18 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/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-20200515095857-1151b9dac4a9/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-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
@ -1065,13 +1158,21 @@ golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/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-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-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/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-20210514084401-e8d321eab015/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-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
|
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
|
||||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
@ -1084,6 +1185,7 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|
@ -1127,12 +1229,29 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||||
|
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ=
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
|
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
|
||||||
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
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=
|
||||||
|
|
@ -1148,12 +1267,26 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb
|
||||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
|
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
|
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||||
|
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.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||||
|
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
||||||
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=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
|
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
|
@ -1174,10 +1307,32 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx
|
||||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8=
|
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/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-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/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-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||||
|
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0=
|
||||||
|
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
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=
|
||||||
|
|
@ -1190,9 +1345,19 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
|
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
|
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||||
|
google.golang.org/grpc v1.35.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.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
|
||||||
|
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-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=
|
||||||
|
|
@ -1222,6 +1387,7 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKW
|
||||||
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/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
|
|
@ -1241,8 +1407,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
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 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
|
|
@ -1254,6 +1420,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-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=
|
||||||
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
|
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
|
||||||
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
|
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
|
||||||
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
|
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
|
||||||
|
|
|
||||||
|
|
@ -63,14 +63,14 @@ func (r *Runtime) compileImageFilters(ctx context.Context, filters []string) ([]
|
||||||
switch key {
|
switch key {
|
||||||
|
|
||||||
case "after", "since":
|
case "after", "since":
|
||||||
img, _, err := r.LookupImage(value, nil)
|
img, _, err := r.LookupImage(value, &LookupImageOptions{IgnorePlatform: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not find local image for filter %q", filter)
|
return nil, errors.Wrapf(err, "could not find local image for filter %q", filter)
|
||||||
}
|
}
|
||||||
filterFuncs = append(filterFuncs, filterAfter(img.Created()))
|
filterFuncs = append(filterFuncs, filterAfter(img.Created()))
|
||||||
|
|
||||||
case "before":
|
case "before":
|
||||||
img, _, err := r.LookupImage(value, nil)
|
img, _, err := r.LookupImage(value, &LookupImageOptions{IgnorePlatform: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not find local image for filter %q", filter)
|
return nil, errors.Wrapf(err, "could not find local image for filter %q", filter)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP
|
||||||
if pullPolicy == config.PullPolicyAlways {
|
if pullPolicy == config.PullPolicyAlways {
|
||||||
return nil, errors.Errorf("pull policy is always but image has been referred to by ID (%s)", name)
|
return nil, errors.Errorf("pull policy is always but image has been referred to by ID (%s)", name)
|
||||||
}
|
}
|
||||||
local, _, err := r.LookupImage(name, nil)
|
local, _, err := r.LookupImage(name, &LookupImageOptions{IgnorePlatform: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -145,9 +145,8 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP
|
||||||
}
|
}
|
||||||
|
|
||||||
localImages := []*Image{}
|
localImages := []*Image{}
|
||||||
lookupOptions := &LookupImageOptions{IgnorePlatform: true}
|
|
||||||
for _, name := range pulledImages {
|
for _, name := range pulledImages {
|
||||||
local, _, err := r.LookupImage(name, lookupOptions)
|
local, _, err := r.LookupImage(name, &LookupImageOptions{IgnorePlatform: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error locating pulled image %q name in containers storage", name)
|
return nil, errors.Wrapf(err, "error locating pulled image %q name in containers storage", name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ func (r *Runtime) Save(ctx context.Context, names []string, format, path string,
|
||||||
// saveSingleImage saves the specified image name to the specified path.
|
// saveSingleImage saves the specified image name to the specified path.
|
||||||
// Supported formats are "oci-archive", "oci-dir" and "docker-dir".
|
// Supported formats are "oci-archive", "oci-dir" and "docker-dir".
|
||||||
func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string, options *SaveOptions) error {
|
func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string, options *SaveOptions) error {
|
||||||
image, imageName, err := r.LookupImage(name, nil)
|
image, imageName, err := r.LookupImage(name, &LookupImageOptions{IgnorePlatform: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +155,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st
|
||||||
visitedNames := make(map[string]bool) // filters duplicate names
|
visitedNames := make(map[string]bool) // filters duplicate names
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
// Look up local images.
|
// Look up local images.
|
||||||
image, imageName, err := r.LookupImage(name, nil)
|
image, imageName, err := r.LookupImage(name, &LookupImageOptions{IgnorePlatform: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -526,9 +526,15 @@ func NewConfig(userConfigPath string) (*Config, error) {
|
||||||
// the defaults from the config parameter will be used for all other fields.
|
// the defaults from the config parameter will be used for all other fields.
|
||||||
func readConfigFromFile(path string, config *Config) error {
|
func readConfigFromFile(path string, config *Config) error {
|
||||||
logrus.Tracef("Reading configuration file %q", path)
|
logrus.Tracef("Reading configuration file %q", path)
|
||||||
if _, err := toml.DecodeFile(path, config); err != nil {
|
meta, err := toml.DecodeFile(path, config)
|
||||||
|
if err != nil {
|
||||||
return errors.Wrapf(err, "decode configuration %v", path)
|
return errors.Wrapf(err, "decode configuration %v", path)
|
||||||
}
|
}
|
||||||
|
keys := meta.Undecoded()
|
||||||
|
if len(keys) > 0 {
|
||||||
|
logrus.Warningf("Failed to decode the keys %q from %q.", keys, path)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/containers/common/pkg/secrets/filedriver"
|
"github.com/containers/common/pkg/secrets/filedriver"
|
||||||
"github.com/containers/common/pkg/secrets/passdriver"
|
"github.com/containers/common/pkg/secrets/passdriver"
|
||||||
|
"github.com/containers/common/pkg/secrets/shelldriver"
|
||||||
"github.com/containers/storage/pkg/lockfile"
|
"github.com/containers/storage/pkg/lockfile"
|
||||||
"github.com/containers/storage/pkg/stringid"
|
"github.com/containers/storage/pkg/stringid"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
@ -281,6 +282,8 @@ func getDriver(name string, opts map[string]string) (SecretsDriver, error) {
|
||||||
}
|
}
|
||||||
case "pass":
|
case "pass":
|
||||||
return passdriver.NewDriver(opts)
|
return passdriver.NewDriver(opts)
|
||||||
|
case "shell":
|
||||||
|
return shelldriver.NewDriver(opts)
|
||||||
}
|
}
|
||||||
return nil, errInvalidDriver
|
return nil, errInvalidDriver
|
||||||
}
|
}
|
||||||
|
|
|
||||||
159
vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go
generated
vendored
Normal file
159
vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go
generated
vendored
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
package shelldriver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
|
||||||
|
// errMissingConfig indicates that one or more of the external actions are not configured
|
||||||
|
errMissingConfig = errors.New("missing config value")
|
||||||
|
|
||||||
|
// errNoSecretData indicates that there is not data associated with an id
|
||||||
|
errNoSecretData = errors.New("no secret data with ID")
|
||||||
|
|
||||||
|
// errInvalidKey indicates that something about your key is wrong
|
||||||
|
errInvalidKey = errors.New("invalid key")
|
||||||
|
)
|
||||||
|
|
||||||
|
type driverConfig struct {
|
||||||
|
// DeleteCommand contains a shell command that deletes a secret.
|
||||||
|
// The secret id is provided as environment variable SECRET_ID
|
||||||
|
DeleteCommand string `mapstructure:"delete"`
|
||||||
|
// ListCommand contains a shell command that lists all secrets.
|
||||||
|
// The output is expected to be one id per line
|
||||||
|
ListCommand string `mapstructure:"list"`
|
||||||
|
// LookupCommand contains a shell command that retrieves a secret.
|
||||||
|
// The secret id is provided as environment variable SECRET_ID
|
||||||
|
LookupCommand string `mapstructure:"lookup"`
|
||||||
|
// StoreCommand contains a shell command that stores a secret.
|
||||||
|
// The secret id is provided as environment variable SECRET_ID
|
||||||
|
// The secret value itself is provied over stdin
|
||||||
|
StoreCommand string `mapstructure:"store"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg *driverConfig) ParseOpts(opts map[string]string) error {
|
||||||
|
if err := mapstructure.Decode(opts, cfg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if cfg.DeleteCommand == "" ||
|
||||||
|
cfg.ListCommand == "" ||
|
||||||
|
cfg.LookupCommand == "" ||
|
||||||
|
cfg.StoreCommand == "" {
|
||||||
|
|
||||||
|
return errMissingConfig
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Driver is the passdriver object
|
||||||
|
type Driver struct {
|
||||||
|
driverConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDriver creates a new secret driver.
|
||||||
|
func NewDriver(opts map[string]string) (*Driver, error) {
|
||||||
|
cfg := &driverConfig{}
|
||||||
|
if err := cfg.ParseOpts(opts); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
driver := &Driver{
|
||||||
|
driverConfig: *cfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
return driver, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns all secret IDs
|
||||||
|
func (d *Driver) List() (secrets []string, err error) {
|
||||||
|
cmd := exec.CommandContext(context.TODO(), "/bin/sh", "-c", d.ListCommand)
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
cmd.Stdout = buf
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := bytes.Split(buf.Bytes(), []byte("\n"))
|
||||||
|
for _, part := range parts {
|
||||||
|
id := strings.Trim(string(part), " \r\n")
|
||||||
|
if len(id) > 0 {
|
||||||
|
secrets = append(secrets, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(secrets)
|
||||||
|
|
||||||
|
return secrets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup returns the bytes associated with a secret ID
|
||||||
|
func (d *Driver) Lookup(id string) ([]byte, error) {
|
||||||
|
if strings.Contains(id, "..") {
|
||||||
|
return nil, errInvalidKey
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.CommandContext(context.TODO(), "/bin/sh", "-c", d.LookupCommand)
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
cmd.Env = append(cmd.Env, "SECRET_ID="+id)
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
cmd.Stdout = buf
|
||||||
|
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(errNoSecretData, id)
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store saves the bytes associated with an ID. An error is returned if the ID already exists
|
||||||
|
func (d *Driver) Store(id string, data []byte) error {
|
||||||
|
if strings.Contains(id, "..") {
|
||||||
|
return errInvalidKey
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.CommandContext(context.TODO(), "/bin/sh", "-c", d.StoreCommand)
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
cmd.Env = append(cmd.Env, "SECRET_ID="+id)
|
||||||
|
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stdin = bytes.NewReader(data)
|
||||||
|
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes the secret associated with the specified ID. An error is returned if no matching secret is found.
|
||||||
|
func (d *Driver) Delete(id string) error {
|
||||||
|
if strings.Contains(id, "..") {
|
||||||
|
return errInvalidKey
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.CommandContext(context.TODO(), "/bin/sh", "-c", d.DeleteCommand)
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
cmd.Env = append(cmd.Env, "SECRET_ID="+id)
|
||||||
|
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(errNoSecretData, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
## unreleased
|
||||||
|
|
||||||
|
* Fix regression where `*time.Time` value would be set to empty and not be sent
|
||||||
|
to decode hooks properly [GH-232]
|
||||||
|
|
||||||
|
## 1.4.0
|
||||||
|
|
||||||
|
* A new decode hook type `DecodeHookFuncValue` has been added that has
|
||||||
|
access to the full values. [GH-183]
|
||||||
|
* Squash is now supported with embedded fields that are struct pointers [GH-205]
|
||||||
|
* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206]
|
||||||
|
|
||||||
|
## 1.3.3
|
||||||
|
|
||||||
|
* Decoding maps from maps creates a settable value for decode hooks [GH-203]
|
||||||
|
|
||||||
|
## 1.3.2
|
||||||
|
|
||||||
|
* Decode into interface type with a struct value is supported [GH-187]
|
||||||
|
|
||||||
|
## 1.3.1
|
||||||
|
|
||||||
|
* Squash should only squash embedded structs. [GH-194]
|
||||||
|
|
||||||
|
## 1.3.0
|
||||||
|
|
||||||
|
* Added `",omitempty"` support. This will ignore zero values in the source
|
||||||
|
structure when encoding. [GH-145]
|
||||||
|
|
||||||
|
## 1.2.3
|
||||||
|
|
||||||
|
* Fix duplicate entries in Keys list with pointer values. [GH-185]
|
||||||
|
|
||||||
|
## 1.2.2
|
||||||
|
|
||||||
|
* Do not add unsettable (unexported) values to the unused metadata key
|
||||||
|
or "remain" value. [GH-150]
|
||||||
|
|
||||||
|
## 1.2.1
|
||||||
|
|
||||||
|
* Go modules checksum mismatch fix
|
||||||
|
|
||||||
|
## 1.2.0
|
||||||
|
|
||||||
|
* Added support to capture unused values in a field using the `",remain"` value
|
||||||
|
in the mapstructure tag. There is an example to showcase usage.
|
||||||
|
* Added `DecoderConfig` option to always squash embedded structs
|
||||||
|
* `json.Number` can decode into `uint` types
|
||||||
|
* Empty slices are preserved and not replaced with nil slices
|
||||||
|
* Fix panic that can occur in when decoding a map into a nil slice of structs
|
||||||
|
* Improved package documentation for godoc
|
||||||
|
|
||||||
|
## 1.1.2
|
||||||
|
|
||||||
|
* Fix error when decode hook decodes interface implementation into interface
|
||||||
|
type. [GH-140]
|
||||||
|
|
||||||
|
## 1.1.1
|
||||||
|
|
||||||
|
* Fix panic that can happen in `decodePtr`
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133]
|
||||||
|
* Support struct to struct decoding [GH-137]
|
||||||
|
* If source map value is nil, then destination map value is nil (instead of empty)
|
||||||
|
* If source slice value is nil, then destination slice value is nil (instead of empty)
|
||||||
|
* If source pointer is nil, then destination pointer is set to nil (instead of
|
||||||
|
allocated zero value of type)
|
||||||
|
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
* Initial tagged stable release.
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013 Mitchell Hashimoto
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
# mapstructure [](https://godoc.org/github.com/mitchellh/mapstructure)
|
||||||
|
|
||||||
|
mapstructure is a Go library for decoding generic map values to structures
|
||||||
|
and vice versa, while providing helpful error handling.
|
||||||
|
|
||||||
|
This library is most useful when decoding values from some data stream (JSON,
|
||||||
|
Gob, etc.) where you don't _quite_ know the structure of the underlying data
|
||||||
|
until you read a part of it. You can therefore read a `map[string]interface{}`
|
||||||
|
and use this library to decode it into the proper underlying native Go
|
||||||
|
structure.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Standard `go get`:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go get github.com/mitchellh/mapstructure
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage & Example
|
||||||
|
|
||||||
|
For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure).
|
||||||
|
|
||||||
|
The `Decode` function has examples associated with it there.
|
||||||
|
|
||||||
|
## But Why?!
|
||||||
|
|
||||||
|
Go offers fantastic standard libraries for decoding formats such as JSON.
|
||||||
|
The standard method is to have a struct pre-created, and populate that struct
|
||||||
|
from the bytes of the encoded format. This is great, but the problem is if
|
||||||
|
you have configuration or an encoding that changes slightly depending on
|
||||||
|
specific fields. For example, consider this JSON:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "person",
|
||||||
|
"name": "Mitchell"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Perhaps we can't populate a specific structure without first reading
|
||||||
|
the "type" field from the JSON. We could always do two passes over the
|
||||||
|
decoding of the JSON (reading the "type" first, and the rest later).
|
||||||
|
However, it is much simpler to just decode this into a `map[string]interface{}`
|
||||||
|
structure, read the "type" key, then use something like this library
|
||||||
|
to decode it into the proper structure.
|
||||||
|
|
@ -0,0 +1,256 @@
|
||||||
|
package mapstructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
|
||||||
|
// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
|
||||||
|
func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
|
||||||
|
// Create variables here so we can reference them with the reflect pkg
|
||||||
|
var f1 DecodeHookFuncType
|
||||||
|
var f2 DecodeHookFuncKind
|
||||||
|
var f3 DecodeHookFuncValue
|
||||||
|
|
||||||
|
// Fill in the variables into this interface and the rest is done
|
||||||
|
// automatically using the reflect package.
|
||||||
|
potential := []interface{}{f1, f2, f3}
|
||||||
|
|
||||||
|
v := reflect.ValueOf(h)
|
||||||
|
vt := v.Type()
|
||||||
|
for _, raw := range potential {
|
||||||
|
pt := reflect.ValueOf(raw).Type()
|
||||||
|
if vt.ConvertibleTo(pt) {
|
||||||
|
return v.Convert(pt).Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeHookExec executes the given decode hook. This should be used
|
||||||
|
// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
|
||||||
|
// that took reflect.Kind instead of reflect.Type.
|
||||||
|
func DecodeHookExec(
|
||||||
|
raw DecodeHookFunc,
|
||||||
|
from reflect.Value, to reflect.Value) (interface{}, error) {
|
||||||
|
|
||||||
|
switch f := typedDecodeHook(raw).(type) {
|
||||||
|
case DecodeHookFuncType:
|
||||||
|
return f(from.Type(), to.Type(), from.Interface())
|
||||||
|
case DecodeHookFuncKind:
|
||||||
|
return f(from.Kind(), to.Kind(), from.Interface())
|
||||||
|
case DecodeHookFuncValue:
|
||||||
|
return f(from, to)
|
||||||
|
default:
|
||||||
|
return nil, errors.New("invalid decode hook signature")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComposeDecodeHookFunc creates a single DecodeHookFunc that
|
||||||
|
// automatically composes multiple DecodeHookFuncs.
|
||||||
|
//
|
||||||
|
// The composed funcs are called in order, with the result of the
|
||||||
|
// previous transformation.
|
||||||
|
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
||||||
|
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
|
||||||
|
var err error
|
||||||
|
var data interface{}
|
||||||
|
newFrom := f
|
||||||
|
for _, f1 := range fs {
|
||||||
|
data, err = DecodeHookExec(f1, newFrom, t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newFrom = reflect.ValueOf(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToSliceHookFunc returns a DecodeHookFunc that converts
|
||||||
|
// string to []string by splitting on the given sep.
|
||||||
|
func StringToSliceHookFunc(sep string) DecodeHookFunc {
|
||||||
|
return func(
|
||||||
|
f reflect.Kind,
|
||||||
|
t reflect.Kind,
|
||||||
|
data interface{}) (interface{}, error) {
|
||||||
|
if f != reflect.String || t != reflect.Slice {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
raw := data.(string)
|
||||||
|
if raw == "" {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Split(raw, sep), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
|
||||||
|
// strings to time.Duration.
|
||||||
|
func StringToTimeDurationHookFunc() DecodeHookFunc {
|
||||||
|
return func(
|
||||||
|
f reflect.Type,
|
||||||
|
t reflect.Type,
|
||||||
|
data interface{}) (interface{}, error) {
|
||||||
|
if f.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
if t != reflect.TypeOf(time.Duration(5)) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert it by parsing
|
||||||
|
return time.ParseDuration(data.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIPHookFunc returns a DecodeHookFunc that converts
|
||||||
|
// strings to net.IP
|
||||||
|
func StringToIPHookFunc() DecodeHookFunc {
|
||||||
|
return func(
|
||||||
|
f reflect.Type,
|
||||||
|
t reflect.Type,
|
||||||
|
data interface{}) (interface{}, error) {
|
||||||
|
if f.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
if t != reflect.TypeOf(net.IP{}) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert it by parsing
|
||||||
|
ip := net.ParseIP(data.(string))
|
||||||
|
if ip == nil {
|
||||||
|
return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIPNetHookFunc returns a DecodeHookFunc that converts
|
||||||
|
// strings to net.IPNet
|
||||||
|
func StringToIPNetHookFunc() DecodeHookFunc {
|
||||||
|
return func(
|
||||||
|
f reflect.Type,
|
||||||
|
t reflect.Type,
|
||||||
|
data interface{}) (interface{}, error) {
|
||||||
|
if f.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
if t != reflect.TypeOf(net.IPNet{}) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert it by parsing
|
||||||
|
_, net, err := net.ParseCIDR(data.(string))
|
||||||
|
return net, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToTimeHookFunc returns a DecodeHookFunc that converts
|
||||||
|
// strings to time.Time.
|
||||||
|
func StringToTimeHookFunc(layout string) DecodeHookFunc {
|
||||||
|
return func(
|
||||||
|
f reflect.Type,
|
||||||
|
t reflect.Type,
|
||||||
|
data interface{}) (interface{}, error) {
|
||||||
|
if f.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
if t != reflect.TypeOf(time.Time{}) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert it by parsing
|
||||||
|
return time.Parse(layout, data.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
|
||||||
|
// the decoder.
|
||||||
|
//
|
||||||
|
// Note that this is significantly different from the WeaklyTypedInput option
|
||||||
|
// of the DecoderConfig.
|
||||||
|
func WeaklyTypedHook(
|
||||||
|
f reflect.Kind,
|
||||||
|
t reflect.Kind,
|
||||||
|
data interface{}) (interface{}, error) {
|
||||||
|
dataVal := reflect.ValueOf(data)
|
||||||
|
switch t {
|
||||||
|
case reflect.String:
|
||||||
|
switch f {
|
||||||
|
case reflect.Bool:
|
||||||
|
if dataVal.Bool() {
|
||||||
|
return "1", nil
|
||||||
|
}
|
||||||
|
return "0", nil
|
||||||
|
case reflect.Float32:
|
||||||
|
return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
|
||||||
|
case reflect.Int:
|
||||||
|
return strconv.FormatInt(dataVal.Int(), 10), nil
|
||||||
|
case reflect.Slice:
|
||||||
|
dataType := dataVal.Type()
|
||||||
|
elemKind := dataType.Elem().Kind()
|
||||||
|
if elemKind == reflect.Uint8 {
|
||||||
|
return string(dataVal.Interface().([]uint8)), nil
|
||||||
|
}
|
||||||
|
case reflect.Uint:
|
||||||
|
return strconv.FormatUint(dataVal.Uint(), 10), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RecursiveStructToMapHookFunc() DecodeHookFunc {
|
||||||
|
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
|
||||||
|
if f.Kind() != reflect.Struct {
|
||||||
|
return f.Interface(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var i interface{} = struct{}{}
|
||||||
|
if t.Type() != reflect.TypeOf(&i).Elem() {
|
||||||
|
return f.Interface(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := make(map[string]interface{})
|
||||||
|
t.Set(reflect.ValueOf(m))
|
||||||
|
|
||||||
|
return f.Interface(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies
|
||||||
|
// strings to the UnmarshalText function, when the target type
|
||||||
|
// implements the encoding.TextUnmarshaler interface
|
||||||
|
func TextUnmarshallerHookFunc() DecodeHookFuncType {
|
||||||
|
return func(
|
||||||
|
f reflect.Type,
|
||||||
|
t reflect.Type,
|
||||||
|
data interface{}) (interface{}, error) {
|
||||||
|
if f.Kind() != reflect.String {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
result := reflect.New(t).Interface()
|
||||||
|
unmarshaller, ok := result.(encoding.TextUnmarshaler)
|
||||||
|
if !ok {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package mapstructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error implements the error interface and can represents multiple
|
||||||
|
// errors that occur in the course of a single decode.
|
||||||
|
type Error struct {
|
||||||
|
Errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Error) Error() string {
|
||||||
|
points := make([]string, len(e.Errors))
|
||||||
|
for i, err := range e.Errors {
|
||||||
|
points[i] = fmt.Sprintf("* %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(points)
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"%d error(s) decoding:\n\n%s",
|
||||||
|
len(e.Errors), strings.Join(points, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrappedErrors implements the errwrap.Wrapper interface to make this
|
||||||
|
// return value more useful with the errwrap and go-multierror libraries.
|
||||||
|
func (e *Error) WrappedErrors() []error {
|
||||||
|
if e == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]error, len(e.Errors))
|
||||||
|
for i, e := range e.Errors {
|
||||||
|
result[i] = errors.New(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendErrors(errors []string, err error) []string {
|
||||||
|
switch e := err.(type) {
|
||||||
|
case *Error:
|
||||||
|
return append(errors, e.Errors...)
|
||||||
|
default:
|
||||||
|
return append(errors, e.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
module github.com/mitchellh/mapstructure
|
||||||
|
|
||||||
|
go 1.14
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,28 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- test
|
|
||||||
- build
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.12.x
|
|
||||||
- 1.13.x
|
|
||||||
- tip
|
|
||||||
|
|
||||||
env: GO111MODULE=on
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- go get -u github.com/kyoh86/richgo
|
|
||||||
- go get -u github.com/mitchellh/gox
|
|
||||||
- curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin latest
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- go: tip
|
|
||||||
include:
|
|
||||||
- stage: build
|
|
||||||
go: 1.13.x
|
|
||||||
script: make cobra_generator
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make test
|
|
||||||
|
|
@ -7,7 +7,6 @@ Cobra is used in many Go projects such as [Kubernetes](http://kubernetes.io/),
|
||||||
name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra.
|
name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra.
|
||||||
|
|
||||||
[](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
|
[](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
|
||||||
[](https://travis-ci.org/spf13/cobra)
|
|
||||||
[](https://godoc.org/github.com/spf13/cobra)
|
[](https://godoc.org/github.com/spf13/cobra)
|
||||||
[](https://goreportcard.com/report/github.com/spf13/cobra)
|
[](https://goreportcard.com/report/github.com/spf13/cobra)
|
||||||
[](https://gophers.slack.com/archives/CD3LP1199)
|
[](https://gophers.slack.com/archives/CD3LP1199)
|
||||||
|
|
@ -19,18 +18,18 @@ name a few. [This list](./projects_using_cobra.md) contains a more extensive lis
|
||||||
* [Commands](#commands)
|
* [Commands](#commands)
|
||||||
* [Flags](#flags)
|
* [Flags](#flags)
|
||||||
- [Installing](#installing)
|
- [Installing](#installing)
|
||||||
- [Getting Started](#getting-started)
|
- [Usage](#usage)
|
||||||
* [Using the Cobra Generator](#using-the-cobra-generator)
|
* [Using the Cobra Generator](user_guide.md#using-the-cobra-generator)
|
||||||
* [Using the Cobra Library](#using-the-cobra-library)
|
* [Using the Cobra Library](user_guide.md#using-the-cobra-library)
|
||||||
* [Working with Flags](#working-with-flags)
|
* [Working with Flags](user_guide.md#working-with-flags)
|
||||||
* [Positional and Custom Arguments](#positional-and-custom-arguments)
|
* [Positional and Custom Arguments](user_guide.md#positional-and-custom-arguments)
|
||||||
* [Example](#example)
|
* [Example](user_guide.md#example)
|
||||||
* [Help Command](#help-command)
|
* [Help Command](user_guide.md#help-command)
|
||||||
* [Usage Message](#usage-message)
|
* [Usage Message](user_guide.md#usage-message)
|
||||||
* [PreRun and PostRun Hooks](#prerun-and-postrun-hooks)
|
* [PreRun and PostRun Hooks](user_guide.md#prerun-and-postrun-hooks)
|
||||||
* [Suggestions when "unknown command" happens](#suggestions-when-unknown-command-happens)
|
* [Suggestions when "unknown command" happens](user_guide.md#suggestions-when-unknown-command-happens)
|
||||||
* [Generating documentation for your command](#generating-documentation-for-your-command)
|
* [Generating documentation for your command](user_guide.md#generating-documentation-for-your-command)
|
||||||
* [Generating shell completions](#generating-shell-completions)
|
* [Generating shell completions](user_guide.md#generating-shell-completions)
|
||||||
- [Contributing](CONTRIBUTING.md)
|
- [Contributing](CONTRIBUTING.md)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
|
|
@ -117,643 +116,9 @@ Next, include Cobra in your application:
|
||||||
import "github.com/spf13/cobra"
|
import "github.com/spf13/cobra"
|
||||||
```
|
```
|
||||||
|
|
||||||
# Getting Started
|
# Usage
|
||||||
|
|
||||||
While you are welcome to provide your own organization, typically a Cobra-based
|
See [User Guide](user_guide.md).
|
||||||
application will follow the following organizational structure:
|
|
||||||
|
|
||||||
```
|
|
||||||
▾ appName/
|
|
||||||
▾ cmd/
|
|
||||||
add.go
|
|
||||||
your.go
|
|
||||||
commands.go
|
|
||||||
here.go
|
|
||||||
main.go
|
|
||||||
```
|
|
||||||
|
|
||||||
In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra.
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"{pathToYourApp}/cmd"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmd.Execute()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using the Cobra Generator
|
|
||||||
|
|
||||||
Cobra provides its own program that will create your application and add any
|
|
||||||
commands you want. It's the easiest way to incorporate Cobra into your application.
|
|
||||||
|
|
||||||
[Here](https://github.com/spf13/cobra/blob/master/cobra/README.md) you can find more information about it.
|
|
||||||
|
|
||||||
## Using the Cobra Library
|
|
||||||
|
|
||||||
To manually implement Cobra you need to create a bare main.go file and a rootCmd file.
|
|
||||||
You will optionally provide additional commands as you see fit.
|
|
||||||
|
|
||||||
### Create rootCmd
|
|
||||||
|
|
||||||
Cobra doesn't require any special constructors. Simply create your commands.
|
|
||||||
|
|
||||||
Ideally you place this in app/cmd/root.go:
|
|
||||||
|
|
||||||
```go
|
|
||||||
var rootCmd = &cobra.Command{
|
|
||||||
Use: "hugo",
|
|
||||||
Short: "Hugo is a very fast static site generator",
|
|
||||||
Long: `A Fast and Flexible Static Site Generator built with
|
|
||||||
love by spf13 and friends in Go.
|
|
||||||
Complete documentation is available at http://hugo.spf13.com`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
// Do Stuff Here
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func Execute() {
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You will additionally define flags and handle configuration in your init() function.
|
|
||||||
|
|
||||||
For example cmd/root.go:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Used for flags.
|
|
||||||
cfgFile string
|
|
||||||
userLicense string
|
|
||||||
|
|
||||||
rootCmd = &cobra.Command{
|
|
||||||
Use: "cobra",
|
|
||||||
Short: "A generator for Cobra based Applications",
|
|
||||||
Long: `Cobra is a CLI library for Go that empowers applications.
|
|
||||||
This application is a tool to generate the needed files
|
|
||||||
to quickly create a Cobra application.`,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Execute executes the root command.
|
|
||||||
func Execute() error {
|
|
||||||
return rootCmd.Execute()
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cobra.OnInitialize(initConfig)
|
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
|
||||||
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
|
|
||||||
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
|
|
||||||
rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
|
|
||||||
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
|
||||||
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
|
|
||||||
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
|
||||||
viper.SetDefault("license", "apache")
|
|
||||||
|
|
||||||
rootCmd.AddCommand(addCmd)
|
|
||||||
rootCmd.AddCommand(initCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initConfig() {
|
|
||||||
if cfgFile != "" {
|
|
||||||
// Use config file from the flag.
|
|
||||||
viper.SetConfigFile(cfgFile)
|
|
||||||
} else {
|
|
||||||
// Find home directory.
|
|
||||||
home, err := homedir.Dir()
|
|
||||||
cobra.CheckErr(err)
|
|
||||||
|
|
||||||
// Search config in home directory with name ".cobra" (without extension).
|
|
||||||
viper.AddConfigPath(home)
|
|
||||||
viper.SetConfigName(".cobra")
|
|
||||||
}
|
|
||||||
|
|
||||||
viper.AutomaticEnv()
|
|
||||||
|
|
||||||
if err := viper.ReadInConfig(); err == nil {
|
|
||||||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create your main.go
|
|
||||||
|
|
||||||
With the root command you need to have your main function execute it.
|
|
||||||
Execute should be run on the root for clarity, though it can be called on any command.
|
|
||||||
|
|
||||||
In a Cobra app, typically the main.go file is very bare. It serves one purpose: to initialize Cobra.
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"{pathToYourApp}/cmd"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmd.Execute()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create additional commands
|
|
||||||
|
|
||||||
Additional commands can be defined and typically are each given their own file
|
|
||||||
inside of the cmd/ directory.
|
|
||||||
|
|
||||||
If you wanted to create a version command you would create cmd/version.go and
|
|
||||||
populate it with the following:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(versionCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var versionCmd = &cobra.Command{
|
|
||||||
Use: "version",
|
|
||||||
Short: "Print the version number of Hugo",
|
|
||||||
Long: `All software has versions. This is Hugo's`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Returning and handling errors
|
|
||||||
|
|
||||||
If you wish to return an error to the caller of a command, `RunE` can be used.
|
|
||||||
|
|
||||||
```go
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(tryCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var tryCmd = &cobra.Command{
|
|
||||||
Use: "try",
|
|
||||||
Short: "Try and possibly fail at something",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
if err := someFunc(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The error can then be caught at the execute function call.
|
|
||||||
|
|
||||||
## Working with Flags
|
|
||||||
|
|
||||||
Flags provide modifiers to control how the action command operates.
|
|
||||||
|
|
||||||
### Assign flags to a command
|
|
||||||
|
|
||||||
Since the flags are defined and used in different locations, we need to
|
|
||||||
define a variable outside with the correct scope to assign the flag to
|
|
||||||
work with.
|
|
||||||
|
|
||||||
```go
|
|
||||||
var Verbose bool
|
|
||||||
var Source string
|
|
||||||
```
|
|
||||||
|
|
||||||
There are two different approaches to assign a flag.
|
|
||||||
|
|
||||||
### Persistent Flags
|
|
||||||
|
|
||||||
A flag can be 'persistent', meaning that this flag will be available to the
|
|
||||||
command it's assigned to as well as every command under that command. For
|
|
||||||
global flags, assign a flag as a persistent flag on the root.
|
|
||||||
|
|
||||||
```go
|
|
||||||
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Local Flags
|
|
||||||
|
|
||||||
A flag can also be assigned locally, which will only apply to that specific command.
|
|
||||||
|
|
||||||
```go
|
|
||||||
localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Local Flag on Parent Commands
|
|
||||||
|
|
||||||
By default, Cobra only parses local flags on the target command, and any local flags on
|
|
||||||
parent commands are ignored. By enabling `Command.TraverseChildren`, Cobra will
|
|
||||||
parse local flags on each command before executing the target command.
|
|
||||||
|
|
||||||
```go
|
|
||||||
command := cobra.Command{
|
|
||||||
Use: "print [OPTIONS] [COMMANDS]",
|
|
||||||
TraverseChildren: true,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Bind Flags with Config
|
|
||||||
|
|
||||||
You can also bind your flags with [viper](https://github.com/spf13/viper):
|
|
||||||
```go
|
|
||||||
var author string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
|
|
||||||
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, the persistent flag `author` is bound with `viper`.
|
|
||||||
**Note**: the variable `author` will not be set to the value from config,
|
|
||||||
when the `--author` flag is not provided by user.
|
|
||||||
|
|
||||||
More in [viper documentation](https://github.com/spf13/viper#working-with-flags).
|
|
||||||
|
|
||||||
### Required flags
|
|
||||||
|
|
||||||
Flags are optional by default. If instead you wish your command to report an error
|
|
||||||
when a flag has not been set, mark it as required:
|
|
||||||
```go
|
|
||||||
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
|
|
||||||
rootCmd.MarkFlagRequired("region")
|
|
||||||
```
|
|
||||||
|
|
||||||
Or, for persistent flags:
|
|
||||||
```go
|
|
||||||
rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
|
|
||||||
rootCmd.MarkPersistentFlagRequired("region")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Positional and Custom Arguments
|
|
||||||
|
|
||||||
Validation of positional arguments can be specified using the `Args` field
|
|
||||||
of `Command`.
|
|
||||||
|
|
||||||
The following validators are built in:
|
|
||||||
|
|
||||||
- `NoArgs` - the command will report an error if there are any positional args.
|
|
||||||
- `ArbitraryArgs` - the command will accept any args.
|
|
||||||
- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`.
|
|
||||||
- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args.
|
|
||||||
- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args.
|
|
||||||
- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args.
|
|
||||||
- `ExactValidArgs(int)` - the command will report an error if there are not exactly N positional args OR if there are any positional args that are not in the `ValidArgs` field of `Command`
|
|
||||||
- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args.
|
|
||||||
|
|
||||||
An example of setting the custom validator:
|
|
||||||
|
|
||||||
```go
|
|
||||||
var cmd = &cobra.Command{
|
|
||||||
Short: "hello",
|
|
||||||
Args: func(cmd *cobra.Command, args []string) error {
|
|
||||||
if len(args) < 1 {
|
|
||||||
return errors.New("requires a color argument")
|
|
||||||
}
|
|
||||||
if myapp.IsValidColor(args[0]) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("invalid color specified: %s", args[0])
|
|
||||||
},
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Println("Hello, World!")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
In the example below, we have defined three commands. Two are at the top level
|
|
||||||
and one (cmdTimes) is a child of one of the top commands. In this case the root
|
|
||||||
is not executable, meaning that a subcommand is required. This is accomplished
|
|
||||||
by not providing a 'Run' for the 'rootCmd'.
|
|
||||||
|
|
||||||
We have only defined one flag for a single command.
|
|
||||||
|
|
||||||
More documentation about flags is available at https://github.com/spf13/pflag
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var echoTimes int
|
|
||||||
|
|
||||||
var cmdPrint = &cobra.Command{
|
|
||||||
Use: "print [string to print]",
|
|
||||||
Short: "Print anything to the screen",
|
|
||||||
Long: `print is for printing anything back to the screen.
|
|
||||||
For many years people have printed back to the screen.`,
|
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Println("Print: " + strings.Join(args, " "))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var cmdEcho = &cobra.Command{
|
|
||||||
Use: "echo [string to echo]",
|
|
||||||
Short: "Echo anything to the screen",
|
|
||||||
Long: `echo is for echoing anything back.
|
|
||||||
Echo works a lot like print, except it has a child command.`,
|
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Println("Echo: " + strings.Join(args, " "))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var cmdTimes = &cobra.Command{
|
|
||||||
Use: "times [string to echo]",
|
|
||||||
Short: "Echo anything to the screen more times",
|
|
||||||
Long: `echo things multiple times back to the user by providing
|
|
||||||
a count and a string.`,
|
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
for i := 0; i < echoTimes; i++ {
|
|
||||||
fmt.Println("Echo: " + strings.Join(args, " "))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input")
|
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{Use: "app"}
|
|
||||||
rootCmd.AddCommand(cmdPrint, cmdEcho)
|
|
||||||
cmdEcho.AddCommand(cmdTimes)
|
|
||||||
rootCmd.Execute()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/).
|
|
||||||
|
|
||||||
## Help Command
|
|
||||||
|
|
||||||
Cobra automatically adds a help command to your application when you have subcommands.
|
|
||||||
This will be called when a user runs 'app help'. Additionally, help will also
|
|
||||||
support all other commands as input. Say, for instance, you have a command called
|
|
||||||
'create' without any additional configuration; Cobra will work when 'app help
|
|
||||||
create' is called. Every command will automatically have the '--help' flag added.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
The following output is automatically generated by Cobra. Nothing beyond the
|
|
||||||
command and flag definitions are needed.
|
|
||||||
|
|
||||||
$ cobra help
|
|
||||||
|
|
||||||
Cobra is a CLI library for Go that empowers applications.
|
|
||||||
This application is a tool to generate the needed files
|
|
||||||
to quickly create a Cobra application.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
cobra [command]
|
|
||||||
|
|
||||||
Available Commands:
|
|
||||||
add Add a command to a Cobra Application
|
|
||||||
help Help about any command
|
|
||||||
init Initialize a Cobra Application
|
|
||||||
|
|
||||||
Flags:
|
|
||||||
-a, --author string author name for copyright attribution (default "YOUR NAME")
|
|
||||||
--config string config file (default is $HOME/.cobra.yaml)
|
|
||||||
-h, --help help for cobra
|
|
||||||
-l, --license string name of license for the project
|
|
||||||
--viper use Viper for configuration (default true)
|
|
||||||
|
|
||||||
Use "cobra [command] --help" for more information about a command.
|
|
||||||
|
|
||||||
|
|
||||||
Help is just a command like any other. There is no special logic or behavior
|
|
||||||
around it. In fact, you can provide your own if you want.
|
|
||||||
|
|
||||||
### Defining your own help
|
|
||||||
|
|
||||||
You can provide your own Help command or your own template for the default command to use
|
|
||||||
with following functions:
|
|
||||||
|
|
||||||
```go
|
|
||||||
cmd.SetHelpCommand(cmd *Command)
|
|
||||||
cmd.SetHelpFunc(f func(*Command, []string))
|
|
||||||
cmd.SetHelpTemplate(s string)
|
|
||||||
```
|
|
||||||
|
|
||||||
The latter two will also apply to any children commands.
|
|
||||||
|
|
||||||
## Usage Message
|
|
||||||
|
|
||||||
When the user provides an invalid flag or invalid command, Cobra responds by
|
|
||||||
showing the user the 'usage'.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
You may recognize this from the help above. That's because the default help
|
|
||||||
embeds the usage as part of its output.
|
|
||||||
|
|
||||||
$ cobra --invalid
|
|
||||||
Error: unknown flag: --invalid
|
|
||||||
Usage:
|
|
||||||
cobra [command]
|
|
||||||
|
|
||||||
Available Commands:
|
|
||||||
add Add a command to a Cobra Application
|
|
||||||
help Help about any command
|
|
||||||
init Initialize a Cobra Application
|
|
||||||
|
|
||||||
Flags:
|
|
||||||
-a, --author string author name for copyright attribution (default "YOUR NAME")
|
|
||||||
--config string config file (default is $HOME/.cobra.yaml)
|
|
||||||
-h, --help help for cobra
|
|
||||||
-l, --license string name of license for the project
|
|
||||||
--viper use Viper for configuration (default true)
|
|
||||||
|
|
||||||
Use "cobra [command] --help" for more information about a command.
|
|
||||||
|
|
||||||
### Defining your own usage
|
|
||||||
You can provide your own usage function or template for Cobra to use.
|
|
||||||
Like help, the function and template are overridable through public methods:
|
|
||||||
|
|
||||||
```go
|
|
||||||
cmd.SetUsageFunc(f func(*Command) error)
|
|
||||||
cmd.SetUsageTemplate(s string)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Version Flag
|
|
||||||
|
|
||||||
Cobra adds a top-level '--version' flag if the Version field is set on the root command.
|
|
||||||
Running an application with the '--version' flag will print the version to stdout using
|
|
||||||
the version template. The template can be customized using the
|
|
||||||
`cmd.SetVersionTemplate(s string)` function.
|
|
||||||
|
|
||||||
## PreRun and PostRun Hooks
|
|
||||||
|
|
||||||
It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order:
|
|
||||||
|
|
||||||
- `PersistentPreRun`
|
|
||||||
- `PreRun`
|
|
||||||
- `Run`
|
|
||||||
- `PostRun`
|
|
||||||
- `PersistentPostRun`
|
|
||||||
|
|
||||||
An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
|
||||||
Use: "root [sub]",
|
|
||||||
Short: "My root command",
|
|
||||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args)
|
|
||||||
},
|
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside rootCmd PreRun with args: %v\n", args)
|
|
||||||
},
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside rootCmd Run with args: %v\n", args)
|
|
||||||
},
|
|
||||||
PostRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside rootCmd PostRun with args: %v\n", args)
|
|
||||||
},
|
|
||||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var subCmd = &cobra.Command{
|
|
||||||
Use: "sub [no options!]",
|
|
||||||
Short: "My subcommand",
|
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside subCmd PreRun with args: %v\n", args)
|
|
||||||
},
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside subCmd Run with args: %v\n", args)
|
|
||||||
},
|
|
||||||
PostRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside subCmd PostRun with args: %v\n", args)
|
|
||||||
},
|
|
||||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
rootCmd.AddCommand(subCmd)
|
|
||||||
|
|
||||||
rootCmd.SetArgs([]string{""})
|
|
||||||
rootCmd.Execute()
|
|
||||||
fmt.Println()
|
|
||||||
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
|
|
||||||
rootCmd.Execute()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
```
|
|
||||||
Inside rootCmd PersistentPreRun with args: []
|
|
||||||
Inside rootCmd PreRun with args: []
|
|
||||||
Inside rootCmd Run with args: []
|
|
||||||
Inside rootCmd PostRun with args: []
|
|
||||||
Inside rootCmd PersistentPostRun with args: []
|
|
||||||
|
|
||||||
Inside rootCmd PersistentPreRun with args: [arg1 arg2]
|
|
||||||
Inside subCmd PreRun with args: [arg1 arg2]
|
|
||||||
Inside subCmd Run with args: [arg1 arg2]
|
|
||||||
Inside subCmd PostRun with args: [arg1 arg2]
|
|
||||||
Inside subCmd PersistentPostRun with args: [arg1 arg2]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Suggestions when "unknown command" happens
|
|
||||||
|
|
||||||
Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ hugo srever
|
|
||||||
Error: unknown command "srever" for "hugo"
|
|
||||||
|
|
||||||
Did you mean this?
|
|
||||||
server
|
|
||||||
|
|
||||||
Run 'hugo --help' for usage.
|
|
||||||
```
|
|
||||||
|
|
||||||
Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion.
|
|
||||||
|
|
||||||
If you need to disable suggestions or tweak the string distance in your command, use:
|
|
||||||
|
|
||||||
```go
|
|
||||||
command.DisableSuggestions = true
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```go
|
|
||||||
command.SuggestionsMinimumDistance = 1
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ kubectl remove
|
|
||||||
Error: unknown command "remove" for "kubectl"
|
|
||||||
|
|
||||||
Did you mean this?
|
|
||||||
delete
|
|
||||||
|
|
||||||
Run 'kubectl help' for usage.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Generating documentation for your command
|
|
||||||
|
|
||||||
Cobra can generate documentation based on subcommands, flags, etc. Read more about it in the [docs generation documentation](doc/README.md).
|
|
||||||
|
|
||||||
## Generating shell completions
|
|
||||||
|
|
||||||
Cobra can generate a shell-completion file for the following shells: bash, zsh, fish, PowerShell. If you add more information to your commands, these completions can be amazingly powerful and flexible. Read more about it in [Shell Completions](shell_completions.md).
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -384,7 +384,7 @@ func writePostscript(buf io.StringWriter, name string) {
|
||||||
name = strings.Replace(name, ":", "__", -1)
|
name = strings.Replace(name, ":", "__", -1)
|
||||||
WriteStringAndCheck(buf, fmt.Sprintf("__start_%s()\n", name))
|
WriteStringAndCheck(buf, fmt.Sprintf("__start_%s()\n", name))
|
||||||
WriteStringAndCheck(buf, fmt.Sprintf(`{
|
WriteStringAndCheck(buf, fmt.Sprintf(`{
|
||||||
local cur prev words cword
|
local cur prev words cword split
|
||||||
declare -A flaghash 2>/dev/null || :
|
declare -A flaghash 2>/dev/null || :
|
||||||
declare -A aliashash 2>/dev/null || :
|
declare -A aliashash 2>/dev/null || :
|
||||||
if declare -F _init_completion >/dev/null 2>&1; then
|
if declare -F _init_completion >/dev/null 2>&1; then
|
||||||
|
|
@ -400,11 +400,13 @@ func writePostscript(buf io.StringWriter, name string) {
|
||||||
local flags_with_completion=()
|
local flags_with_completion=()
|
||||||
local flags_completion=()
|
local flags_completion=()
|
||||||
local commands=("%[1]s")
|
local commands=("%[1]s")
|
||||||
|
local command_aliases=()
|
||||||
local must_have_one_flag=()
|
local must_have_one_flag=()
|
||||||
local must_have_one_noun=()
|
local must_have_one_noun=()
|
||||||
local has_completion_function
|
local has_completion_function
|
||||||
local last_command
|
local last_command
|
||||||
local nouns=()
|
local nouns=()
|
||||||
|
local noun_aliases=()
|
||||||
|
|
||||||
__%[1]s_handle_word
|
__%[1]s_handle_word
|
||||||
}
|
}
|
||||||
|
|
@ -510,7 +512,7 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) {
|
||||||
|
|
||||||
// Setup annotations for go completions for registered flags
|
// Setup annotations for go completions for registered flags
|
||||||
func prepareCustomAnnotationsForFlags(cmd *Command) {
|
func prepareCustomAnnotationsForFlags(cmd *Command) {
|
||||||
for flag := range flagCompletionFunctions {
|
for flag := range cmd.Root().flagCompletionFunctions {
|
||||||
// Make sure the completion script calls the __*_go_custom_completion function for
|
// Make sure the completion script calls the __*_go_custom_completion function for
|
||||||
// every registered flag. We need to do this here (and not when the flag was registered
|
// every registered flag. We need to do this here (and not when the flag was registered
|
||||||
// for completion) so that we can know the root command name for the prefix
|
// for completion) so that we can know the root command name for the prefix
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ Please refer to [Shell Completions](shell_completions.md) for details.
|
||||||
|
|
||||||
For backward compatibility, Cobra still supports its legacy dynamic completion solution (described below). Unlike the `ValidArgsFunction` solution, the legacy solution will only work for Bash shell-completion and not for other shells. This legacy solution can be used along-side `ValidArgsFunction` and `RegisterFlagCompletionFunc()`, as long as both solutions are not used for the same command. This provides a path to gradually migrate from the legacy solution to the new solution.
|
For backward compatibility, Cobra still supports its legacy dynamic completion solution (described below). Unlike the `ValidArgsFunction` solution, the legacy solution will only work for Bash shell-completion and not for other shells. This legacy solution can be used along-side `ValidArgsFunction` and `RegisterFlagCompletionFunc()`, as long as both solutions are not used for the same command. This provides a path to gradually migrate from the legacy solution to the new solution.
|
||||||
|
|
||||||
|
**Note**: Cobra's default `completion` command uses bash completion V2. If you are currently using Cobra's legacy dynamic completion solution, you should not use the default `completion` command but continue using your own.
|
||||||
|
|
||||||
The legacy solution allows you to inject bash functions into the bash completion script. Those bash functions are responsible for providing the completion choices for your own completions.
|
The legacy solution allows you to inject bash functions into the bash completion script. Those bash functions are responsible for providing the completion choices for your own completions.
|
||||||
|
|
||||||
Some code that works in kubernetes:
|
Some code that works in kubernetes:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,302 @@
|
||||||
|
package cobra
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Command) genBashCompletion(w io.Writer, includeDesc bool) error {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
genBashComp(buf, c.Name(), includeDesc)
|
||||||
|
_, err := buf.WriteTo(w)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func genBashComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||||
|
compCmd := ShellCompRequestCmd
|
||||||
|
if !includeDesc {
|
||||||
|
compCmd = ShellCompNoDescRequestCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteStringAndCheck(buf, fmt.Sprintf(`# bash completion V2 for %-36[1]s -*- shell-script -*-
|
||||||
|
|
||||||
|
__%[1]s_debug()
|
||||||
|
{
|
||||||
|
if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
|
||||||
|
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Macs have bash3 for which the bash-completion package doesn't include
|
||||||
|
# _init_completion. This is a minimal version of that function.
|
||||||
|
__%[1]s_init_completion()
|
||||||
|
{
|
||||||
|
COMPREPLY=()
|
||||||
|
_get_comp_words_by_ref "$@" cur prev words cword
|
||||||
|
}
|
||||||
|
|
||||||
|
# This function calls the %[1]s program to obtain the completion
|
||||||
|
# results and the directive. It fills the 'out' and 'directive' vars.
|
||||||
|
__%[1]s_get_completion_results() {
|
||||||
|
local requestComp lastParam lastChar args
|
||||||
|
|
||||||
|
# Prepare the command to request completions for the program.
|
||||||
|
# Calling ${words[0]} instead of directly %[1]s allows to handle aliases
|
||||||
|
args=("${words[@]:1}")
|
||||||
|
requestComp="${words[0]} %[2]s ${args[*]}"
|
||||||
|
|
||||||
|
lastParam=${words[$((${#words[@]}-1))]}
|
||||||
|
lastChar=${lastParam:$((${#lastParam}-1)):1}
|
||||||
|
__%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}"
|
||||||
|
|
||||||
|
if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
|
||||||
|
# If the last parameter is complete (there is a space following it)
|
||||||
|
# We add an extra empty parameter so we can indicate this to the go method.
|
||||||
|
__%[1]s_debug "Adding extra empty parameter"
|
||||||
|
requestComp="${requestComp} ''"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# When completing a flag with an = (e.g., %[1]s -n=<TAB>)
|
||||||
|
# bash focuses on the part after the =, so we need to remove
|
||||||
|
# the flag part from $cur
|
||||||
|
if [[ "${cur}" == -*=* ]]; then
|
||||||
|
cur="${cur#*=}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
__%[1]s_debug "Calling ${requestComp}"
|
||||||
|
# Use eval to handle any environment variables and such
|
||||||
|
out=$(eval "${requestComp}" 2>/dev/null)
|
||||||
|
|
||||||
|
# Extract the directive integer at the very end of the output following a colon (:)
|
||||||
|
directive=${out##*:}
|
||||||
|
# Remove the directive
|
||||||
|
out=${out%%:*}
|
||||||
|
if [ "${directive}" = "${out}" ]; then
|
||||||
|
# There is not directive specified
|
||||||
|
directive=0
|
||||||
|
fi
|
||||||
|
__%[1]s_debug "The completion directive is: ${directive}"
|
||||||
|
__%[1]s_debug "The completions are: ${out[*]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__%[1]s_process_completion_results() {
|
||||||
|
local shellCompDirectiveError=%[3]d
|
||||||
|
local shellCompDirectiveNoSpace=%[4]d
|
||||||
|
local shellCompDirectiveNoFileComp=%[5]d
|
||||||
|
local shellCompDirectiveFilterFileExt=%[6]d
|
||||||
|
local shellCompDirectiveFilterDirs=%[7]d
|
||||||
|
|
||||||
|
if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
|
||||||
|
# Error code. No completion.
|
||||||
|
__%[1]s_debug "Received error from custom completion go code"
|
||||||
|
return
|
||||||
|
else
|
||||||
|
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
|
||||||
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
|
__%[1]s_debug "Activating no space"
|
||||||
|
compopt -o nospace
|
||||||
|
else
|
||||||
|
__%[1]s_debug "No space directive not supported in this version of bash"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
|
||||||
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
|
__%[1]s_debug "Activating no file completion"
|
||||||
|
compopt +o default
|
||||||
|
else
|
||||||
|
__%[1]s_debug "No file completion directive not supported in this version of bash"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
|
||||||
|
# File extension filtering
|
||||||
|
local fullFilter filter filteringCmd
|
||||||
|
|
||||||
|
# Do not use quotes around the $out variable or else newline
|
||||||
|
# characters will be kept.
|
||||||
|
for filter in ${out[*]}; do
|
||||||
|
fullFilter+="$filter|"
|
||||||
|
done
|
||||||
|
|
||||||
|
filteringCmd="_filedir $fullFilter"
|
||||||
|
__%[1]s_debug "File filtering command: $filteringCmd"
|
||||||
|
$filteringCmd
|
||||||
|
elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
|
||||||
|
# File completion for directories only
|
||||||
|
|
||||||
|
# Use printf to strip any trailing newline
|
||||||
|
local subdir
|
||||||
|
subdir=$(printf "%%s" "${out[0]}")
|
||||||
|
if [ -n "$subdir" ]; then
|
||||||
|
__%[1]s_debug "Listing directories in $subdir"
|
||||||
|
pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
|
||||||
|
else
|
||||||
|
__%[1]s_debug "Listing directories in ."
|
||||||
|
_filedir -d
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
__%[1]s_handle_standard_completion_case
|
||||||
|
fi
|
||||||
|
|
||||||
|
__%[1]s_handle_special_char "$cur" :
|
||||||
|
__%[1]s_handle_special_char "$cur" =
|
||||||
|
}
|
||||||
|
|
||||||
|
__%[1]s_handle_standard_completion_case() {
|
||||||
|
local tab comp
|
||||||
|
tab=$(printf '\t')
|
||||||
|
|
||||||
|
local longest=0
|
||||||
|
# Look for the longest completion so that we can format things nicely
|
||||||
|
while IFS='' read -r comp; do
|
||||||
|
# Strip any description before checking the length
|
||||||
|
comp=${comp%%%%$tab*}
|
||||||
|
# Only consider the completions that match
|
||||||
|
comp=$(compgen -W "$comp" -- "$cur")
|
||||||
|
if ((${#comp}>longest)); then
|
||||||
|
longest=${#comp}
|
||||||
|
fi
|
||||||
|
done < <(printf "%%s\n" "${out[@]}")
|
||||||
|
|
||||||
|
local completions=()
|
||||||
|
while IFS='' read -r comp; do
|
||||||
|
if [ -z "$comp" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
__%[1]s_debug "Original comp: $comp"
|
||||||
|
comp="$(__%[1]s_format_comp_descriptions "$comp" "$longest")"
|
||||||
|
__%[1]s_debug "Final comp: $comp"
|
||||||
|
completions+=("$comp")
|
||||||
|
done < <(printf "%%s\n" "${out[@]}")
|
||||||
|
|
||||||
|
while IFS='' read -r comp; do
|
||||||
|
COMPREPLY+=("$comp")
|
||||||
|
done < <(compgen -W "${completions[*]}" -- "$cur")
|
||||||
|
|
||||||
|
# If there is a single completion left, remove the description text
|
||||||
|
if [ ${#COMPREPLY[*]} -eq 1 ]; then
|
||||||
|
__%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
|
||||||
|
comp="${COMPREPLY[0]%%%% *}"
|
||||||
|
__%[1]s_debug "Removed description from single completion, which is now: ${comp}"
|
||||||
|
COMPREPLY=()
|
||||||
|
COMPREPLY+=("$comp")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
__%[1]s_handle_special_char()
|
||||||
|
{
|
||||||
|
local comp="$1"
|
||||||
|
local char=$2
|
||||||
|
if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
|
||||||
|
local word=${comp%%"${comp##*${char}}"}
|
||||||
|
local idx=${#COMPREPLY[*]}
|
||||||
|
while [[ $((--idx)) -ge 0 ]]; do
|
||||||
|
COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
__%[1]s_format_comp_descriptions()
|
||||||
|
{
|
||||||
|
local tab
|
||||||
|
tab=$(printf '\t')
|
||||||
|
local comp="$1"
|
||||||
|
local longest=$2
|
||||||
|
|
||||||
|
# Properly format the description string which follows a tab character if there is one
|
||||||
|
if [[ "$comp" == *$tab* ]]; then
|
||||||
|
desc=${comp#*$tab}
|
||||||
|
comp=${comp%%%%$tab*}
|
||||||
|
|
||||||
|
# $COLUMNS stores the current shell width.
|
||||||
|
# Remove an extra 4 because we add 2 spaces and 2 parentheses.
|
||||||
|
maxdesclength=$(( COLUMNS - longest - 4 ))
|
||||||
|
|
||||||
|
# Make sure we can fit a description of at least 8 characters
|
||||||
|
# if we are to align the descriptions.
|
||||||
|
if [[ $maxdesclength -gt 8 ]]; then
|
||||||
|
# Add the proper number of spaces to align the descriptions
|
||||||
|
for ((i = ${#comp} ; i < longest ; i++)); do
|
||||||
|
comp+=" "
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Don't pad the descriptions so we can fit more text after the completion
|
||||||
|
maxdesclength=$(( COLUMNS - ${#comp} - 4 ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If there is enough space for any description text,
|
||||||
|
# truncate the descriptions that are too long for the shell width
|
||||||
|
if [ $maxdesclength -gt 0 ]; then
|
||||||
|
if [ ${#desc} -gt $maxdesclength ]; then
|
||||||
|
desc=${desc:0:$(( maxdesclength - 1 ))}
|
||||||
|
desc+="…"
|
||||||
|
fi
|
||||||
|
comp+=" ($desc)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Must use printf to escape all special characters
|
||||||
|
printf "%%q" "${comp}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__start_%[1]s()
|
||||||
|
{
|
||||||
|
local cur prev words cword split
|
||||||
|
|
||||||
|
COMPREPLY=()
|
||||||
|
|
||||||
|
# Call _init_completion from the bash-completion package
|
||||||
|
# to prepare the arguments properly
|
||||||
|
if declare -F _init_completion >/dev/null 2>&1; then
|
||||||
|
_init_completion -n "=:" || return
|
||||||
|
else
|
||||||
|
__%[1]s_init_completion -n "=:" || return
|
||||||
|
fi
|
||||||
|
|
||||||
|
__%[1]s_debug
|
||||||
|
__%[1]s_debug "========= starting completion logic =========="
|
||||||
|
__%[1]s_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword"
|
||||||
|
|
||||||
|
# The user could have moved the cursor backwards on the command-line.
|
||||||
|
# We need to trigger completion from the $cword location, so we need
|
||||||
|
# to truncate the command-line ($words) up to the $cword location.
|
||||||
|
words=("${words[@]:0:$cword+1}")
|
||||||
|
__%[1]s_debug "Truncated words[*]: ${words[*]},"
|
||||||
|
|
||||||
|
local out directive
|
||||||
|
__%[1]s_get_completion_results
|
||||||
|
__%[1]s_process_completion_results
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
|
complete -o default -F __start_%[1]s %[1]s
|
||||||
|
else
|
||||||
|
complete -o default -o nospace -F __start_%[1]s %[1]s
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ex: ts=4 sw=4 et filetype=sh
|
||||||
|
`, name, compCmd,
|
||||||
|
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||||
|
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenBashCompletionFileV2 generates Bash completion version 2.
|
||||||
|
func (c *Command) GenBashCompletionFileV2(filename string, includeDesc bool) error {
|
||||||
|
outFile, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
|
||||||
|
return c.GenBashCompletionV2(outFile, includeDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenBashCompletionV2 generates Bash completion file version 2
|
||||||
|
// and writes it to the passed writer.
|
||||||
|
func (c *Command) GenBashCompletionV2(w io.Writer, includeDesc bool) error {
|
||||||
|
return c.genBashCompletion(w, includeDesc)
|
||||||
|
}
|
||||||
|
|
@ -63,9 +63,9 @@ type Command struct {
|
||||||
// Example is examples of how to use the command.
|
// Example is examples of how to use the command.
|
||||||
Example string
|
Example string
|
||||||
|
|
||||||
// ValidArgs is list of all valid non-flag arguments that are accepted in bash completions
|
// ValidArgs is list of all valid non-flag arguments that are accepted in shell completions
|
||||||
ValidArgs []string
|
ValidArgs []string
|
||||||
// ValidArgsFunction is an optional function that provides valid non-flag arguments for bash completion.
|
// ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion.
|
||||||
// It is a dynamic version of using ValidArgs.
|
// It is a dynamic version of using ValidArgs.
|
||||||
// Only one of ValidArgs and ValidArgsFunction can be used for a command.
|
// Only one of ValidArgs and ValidArgsFunction can be used for a command.
|
||||||
ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
|
ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
|
||||||
|
|
@ -74,11 +74,12 @@ type Command struct {
|
||||||
Args PositionalArgs
|
Args PositionalArgs
|
||||||
|
|
||||||
// ArgAliases is List of aliases for ValidArgs.
|
// ArgAliases is List of aliases for ValidArgs.
|
||||||
// These are not suggested to the user in the bash completion,
|
// These are not suggested to the user in the shell completion,
|
||||||
// but accepted if entered manually.
|
// but accepted if entered manually.
|
||||||
ArgAliases []string
|
ArgAliases []string
|
||||||
|
|
||||||
// BashCompletionFunction is custom functions used by the bash autocompletion generator.
|
// BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator.
|
||||||
|
// For portability with other shells, it is recommended to instead use ValidArgsFunction
|
||||||
BashCompletionFunction string
|
BashCompletionFunction string
|
||||||
|
|
||||||
// Deprecated defines, if this command is deprecated and should print this string when used.
|
// Deprecated defines, if this command is deprecated and should print this string when used.
|
||||||
|
|
@ -141,6 +142,9 @@ type Command struct {
|
||||||
// that we can use on every pflag set and children commands
|
// that we can use on every pflag set and children commands
|
||||||
globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
|
globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
|
||||||
|
|
||||||
|
//flagCompletionFunctions is map of flag completion functions.
|
||||||
|
flagCompletionFunctions map[*flag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
|
||||||
|
|
||||||
// usageFunc is usage func defined by user.
|
// usageFunc is usage func defined by user.
|
||||||
usageFunc func(*Command) error
|
usageFunc func(*Command) error
|
||||||
// usageTemplate is usage template defined by user.
|
// usageTemplate is usage template defined by user.
|
||||||
|
|
@ -168,6 +172,9 @@ type Command struct {
|
||||||
//FParseErrWhitelist flag parse errors to be ignored
|
//FParseErrWhitelist flag parse errors to be ignored
|
||||||
FParseErrWhitelist FParseErrWhitelist
|
FParseErrWhitelist FParseErrWhitelist
|
||||||
|
|
||||||
|
// CompletionOptions is a set of options to control the handling of shell completion
|
||||||
|
CompletionOptions CompletionOptions
|
||||||
|
|
||||||
// commandsAreSorted defines, if command slice are sorted or not.
|
// commandsAreSorted defines, if command slice are sorted or not.
|
||||||
commandsAreSorted bool
|
commandsAreSorted bool
|
||||||
// commandCalledAs is the name or alias value used to call this command.
|
// commandCalledAs is the name or alias value used to call this command.
|
||||||
|
|
@ -884,7 +891,8 @@ func (c *Command) preRun() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteContext is the same as Execute(), but sets the ctx on the command.
|
// ExecuteContext is the same as Execute(), but sets the ctx on the command.
|
||||||
// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle functions.
|
// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs
|
||||||
|
// functions.
|
||||||
func (c *Command) ExecuteContext(ctx context.Context) error {
|
func (c *Command) ExecuteContext(ctx context.Context) error {
|
||||||
c.ctx = ctx
|
c.ctx = ctx
|
||||||
return c.Execute()
|
return c.Execute()
|
||||||
|
|
@ -898,6 +906,14 @@ func (c *Command) Execute() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecuteContextC is the same as ExecuteC(), but sets the ctx on the command.
|
||||||
|
// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs
|
||||||
|
// functions.
|
||||||
|
func (c *Command) ExecuteContextC(ctx context.Context) (*Command, error) {
|
||||||
|
c.ctx = ctx
|
||||||
|
return c.ExecuteC()
|
||||||
|
}
|
||||||
|
|
||||||
// ExecuteC executes the command.
|
// ExecuteC executes the command.
|
||||||
func (c *Command) ExecuteC() (cmd *Command, err error) {
|
func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
if c.ctx == nil {
|
if c.ctx == nil {
|
||||||
|
|
@ -914,9 +930,10 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
preExecHookFn(c)
|
preExecHookFn(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize help as the last point possible to allow for user
|
// initialize help at the last point to allow for user overriding
|
||||||
// overriding
|
|
||||||
c.InitDefaultHelpCmd()
|
c.InitDefaultHelpCmd()
|
||||||
|
// initialize completion at the last point to allow for user overriding
|
||||||
|
c.initDefaultCompletionCmd()
|
||||||
|
|
||||||
args := c.args
|
args := c.args
|
||||||
|
|
||||||
|
|
@ -925,7 +942,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
args = os.Args[1:]
|
args = os.Args[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize the hidden command to be used for bash completion
|
// initialize the hidden command to be used for shell completion
|
||||||
c.initCompleteCmd(args)
|
c.initCompleteCmd(args)
|
||||||
|
|
||||||
var flags []string
|
var flags []string
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,19 @@ const (
|
||||||
ShellCompNoDescRequestCmd = "__completeNoDesc"
|
ShellCompNoDescRequestCmd = "__completeNoDesc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Global map of flag completion functions.
|
|
||||||
var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){}
|
|
||||||
|
|
||||||
// ShellCompDirective is a bit map representing the different behaviors the shell
|
// ShellCompDirective is a bit map representing the different behaviors the shell
|
||||||
// can be instructed to have once completions have been provided.
|
// can be instructed to have once completions have been provided.
|
||||||
type ShellCompDirective int
|
type ShellCompDirective int
|
||||||
|
|
||||||
|
type flagCompError struct {
|
||||||
|
subCommand string
|
||||||
|
flagName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *flagCompError) Error() string {
|
||||||
|
return "Subcommand '" + e.subCommand + "' does not support flag '" + e.flagName + "'"
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ShellCompDirectiveError indicates an error occurred and completions should be ignored.
|
// ShellCompDirectiveError indicates an error occurred and completions should be ignored.
|
||||||
ShellCompDirectiveError ShellCompDirective = 1 << iota
|
ShellCompDirectiveError ShellCompDirective = 1 << iota
|
||||||
|
|
@ -34,7 +40,6 @@ const (
|
||||||
|
|
||||||
// ShellCompDirectiveNoFileComp indicates that the shell should not provide
|
// ShellCompDirectiveNoFileComp indicates that the shell should not provide
|
||||||
// file completion even when no completion is provided.
|
// file completion even when no completion is provided.
|
||||||
// This currently does not work for zsh or bash < 4
|
|
||||||
ShellCompDirectiveNoFileComp
|
ShellCompDirectiveNoFileComp
|
||||||
|
|
||||||
// ShellCompDirectiveFilterFileExt indicates that the provided completions
|
// ShellCompDirectiveFilterFileExt indicates that the provided completions
|
||||||
|
|
@ -63,16 +68,47 @@ const (
|
||||||
ShellCompDirectiveDefault ShellCompDirective = 0
|
ShellCompDirectiveDefault ShellCompDirective = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Constants for the completion command
|
||||||
|
compCmdName = "completion"
|
||||||
|
compCmdNoDescFlagName = "no-descriptions"
|
||||||
|
compCmdNoDescFlagDesc = "disable completion descriptions"
|
||||||
|
compCmdNoDescFlagDefault = false
|
||||||
|
)
|
||||||
|
|
||||||
|
// CompletionOptions are the options to control shell completion
|
||||||
|
type CompletionOptions struct {
|
||||||
|
// DisableDefaultCmd prevents Cobra from creating a default 'completion' command
|
||||||
|
DisableDefaultCmd bool
|
||||||
|
// DisableNoDescFlag prevents Cobra from creating the '--no-descriptions' flag
|
||||||
|
// for shells that support completion descriptions
|
||||||
|
DisableNoDescFlag bool
|
||||||
|
// DisableDescriptions turns off all completion descriptions for shells
|
||||||
|
// that support them
|
||||||
|
DisableDescriptions bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoFileCompletions can be used to disable file completion for commands that should
|
||||||
|
// not trigger file completions.
|
||||||
|
func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||||
|
return nil, ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag.
|
// RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag.
|
||||||
func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)) error {
|
func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)) error {
|
||||||
flag := c.Flag(flagName)
|
flag := c.Flag(flagName)
|
||||||
if flag == nil {
|
if flag == nil {
|
||||||
return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName)
|
return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName)
|
||||||
}
|
}
|
||||||
if _, exists := flagCompletionFunctions[flag]; exists {
|
|
||||||
|
root := c.Root()
|
||||||
|
if _, exists := root.flagCompletionFunctions[flag]; exists {
|
||||||
return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName)
|
return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName)
|
||||||
}
|
}
|
||||||
flagCompletionFunctions[flag] = f
|
if root.flagCompletionFunctions == nil {
|
||||||
|
root.flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){}
|
||||||
|
}
|
||||||
|
root.flagCompletionFunctions[flag] = f
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,10 +185,6 @@ func (c *Command) initCompleteCmd(args []string) {
|
||||||
fmt.Fprintln(finalCmd.OutOrStdout(), comp)
|
fmt.Fprintln(finalCmd.OutOrStdout(), comp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if directive >= shellCompDirectiveMaxValue {
|
|
||||||
directive = ShellCompDirectiveDefault
|
|
||||||
}
|
|
||||||
|
|
||||||
// As the last printout, print the completion directive for the completion script to parse.
|
// As the last printout, print the completion directive for the completion script to parse.
|
||||||
// The directive integer must be that last character following a single colon (:).
|
// The directive integer must be that last character following a single colon (:).
|
||||||
// The completion script expects :<directive>
|
// The completion script expects :<directive>
|
||||||
|
|
@ -195,23 +227,41 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
||||||
// Unable to find the real command. E.g., <program> someInvalidCmd <TAB>
|
// Unable to find the real command. E.g., <program> someInvalidCmd <TAB>
|
||||||
return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs)
|
return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs)
|
||||||
}
|
}
|
||||||
|
finalCmd.ctx = c.ctx
|
||||||
|
|
||||||
// Check if we are doing flag value completion before parsing the flags.
|
// Check if we are doing flag value completion before parsing the flags.
|
||||||
// This is important because if we are completing a flag value, we need to also
|
// This is important because if we are completing a flag value, we need to also
|
||||||
// remove the flag name argument from the list of finalArgs or else the parsing
|
// remove the flag name argument from the list of finalArgs or else the parsing
|
||||||
// could fail due to an invalid value (incomplete) for the flag.
|
// could fail due to an invalid value (incomplete) for the flag.
|
||||||
flag, finalArgs, toComplete, err := checkIfFlagCompletion(finalCmd, finalArgs, toComplete)
|
flag, finalArgs, toComplete, flagErr := checkIfFlagCompletion(finalCmd, finalArgs, toComplete)
|
||||||
if err != nil {
|
|
||||||
// Error while attempting to parse flags
|
// Check if interspersed is false or -- was set on a previous arg.
|
||||||
return finalCmd, []string{}, ShellCompDirectiveDefault, err
|
// This works by counting the arguments. Normally -- is not counted as arg but
|
||||||
}
|
// if -- was already set or interspersed is false and there is already one arg then
|
||||||
|
// the extra added -- is counted as arg.
|
||||||
|
flagCompletion := true
|
||||||
|
_ = finalCmd.ParseFlags(append(finalArgs, "--"))
|
||||||
|
newArgCount := finalCmd.Flags().NArg()
|
||||||
|
|
||||||
// Parse the flags early so we can check if required flags are set
|
// Parse the flags early so we can check if required flags are set
|
||||||
if err = finalCmd.ParseFlags(finalArgs); err != nil {
|
if err = finalCmd.ParseFlags(finalArgs); err != nil {
|
||||||
return finalCmd, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
|
return finalCmd, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if flag != nil {
|
realArgCount := finalCmd.Flags().NArg()
|
||||||
|
if newArgCount > realArgCount {
|
||||||
|
// don't do flag completion (see above)
|
||||||
|
flagCompletion = false
|
||||||
|
}
|
||||||
|
// Error while attempting to parse flags
|
||||||
|
if flagErr != nil {
|
||||||
|
// If error type is flagCompError and we don't want flagCompletion we should ignore the error
|
||||||
|
if _, ok := flagErr.(*flagCompError); !(ok && !flagCompletion) {
|
||||||
|
return finalCmd, []string{}, ShellCompDirectiveDefault, flagErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag != nil && flagCompletion {
|
||||||
// Check if we are completing a flag value subject to annotations
|
// Check if we are completing a flag value subject to annotations
|
||||||
if validExts, present := flag.Annotations[BashCompFilenameExt]; present {
|
if validExts, present := flag.Annotations[BashCompFilenameExt]; present {
|
||||||
if len(validExts) != 0 {
|
if len(validExts) != 0 {
|
||||||
|
|
@ -238,7 +288,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
||||||
// When doing completion of a flag name, as soon as an argument starts with
|
// When doing completion of a flag name, as soon as an argument starts with
|
||||||
// a '-' we know it is a flag. We cannot use isFlagArg() here as it requires
|
// a '-' we know it is a flag. We cannot use isFlagArg() here as it requires
|
||||||
// the flag name to be complete
|
// the flag name to be complete
|
||||||
if flag == nil && len(toComplete) > 0 && toComplete[0] == '-' && !strings.Contains(toComplete, "=") {
|
if flag == nil && len(toComplete) > 0 && toComplete[0] == '-' && !strings.Contains(toComplete, "=") && flagCompletion {
|
||||||
var completions []string
|
var completions []string
|
||||||
|
|
||||||
// First check for required flags
|
// First check for required flags
|
||||||
|
|
@ -302,7 +352,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
||||||
if len(finalArgs) == 0 && !foundLocalNonPersistentFlag {
|
if len(finalArgs) == 0 && !foundLocalNonPersistentFlag {
|
||||||
// We only complete sub-commands if:
|
// We only complete sub-commands if:
|
||||||
// - there are no arguments on the command-line and
|
// - there are no arguments on the command-line and
|
||||||
// - there are no local, non-peristent flag on the command-line or TraverseChildren is true
|
// - there are no local, non-persistent flags on the command-line or TraverseChildren is true
|
||||||
for _, subCmd := range finalCmd.Commands() {
|
for _, subCmd := range finalCmd.Commands() {
|
||||||
if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand {
|
if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand {
|
||||||
if strings.HasPrefix(subCmd.Name(), toComplete) {
|
if strings.HasPrefix(subCmd.Name(), toComplete) {
|
||||||
|
|
@ -351,8 +401,8 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
||||||
|
|
||||||
// Find the completion function for the flag or command
|
// Find the completion function for the flag or command
|
||||||
var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
|
var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
|
||||||
if flag != nil {
|
if flag != nil && flagCompletion {
|
||||||
completionFn = flagCompletionFunctions[flag]
|
completionFn = c.Root().flagCompletionFunctions[flag]
|
||||||
} else {
|
} else {
|
||||||
completionFn = finalCmd.ValidArgsFunction
|
completionFn = finalCmd.ValidArgsFunction
|
||||||
}
|
}
|
||||||
|
|
@ -435,6 +485,7 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
|
||||||
var flagName string
|
var flagName string
|
||||||
trimmedArgs := args
|
trimmedArgs := args
|
||||||
flagWithEqual := false
|
flagWithEqual := false
|
||||||
|
orgLastArg := lastArg
|
||||||
|
|
||||||
// When doing completion of a flag name, as soon as an argument starts with
|
// When doing completion of a flag name, as soon as an argument starts with
|
||||||
// a '-' we know it is a flag. We cannot use isFlagArg() here as that function
|
// a '-' we know it is a flag. We cannot use isFlagArg() here as that function
|
||||||
|
|
@ -442,7 +493,16 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
|
||||||
if len(lastArg) > 0 && lastArg[0] == '-' {
|
if len(lastArg) > 0 && lastArg[0] == '-' {
|
||||||
if index := strings.Index(lastArg, "="); index >= 0 {
|
if index := strings.Index(lastArg, "="); index >= 0 {
|
||||||
// Flag with an =
|
// Flag with an =
|
||||||
flagName = strings.TrimLeft(lastArg[:index], "-")
|
if strings.HasPrefix(lastArg[:index], "--") {
|
||||||
|
// Flag has full name
|
||||||
|
flagName = lastArg[2:index]
|
||||||
|
} else {
|
||||||
|
// Flag is shorthand
|
||||||
|
// We have to get the last shorthand flag name
|
||||||
|
// e.g. `-asd` => d to provide the correct completion
|
||||||
|
// https://github.com/spf13/cobra/issues/1257
|
||||||
|
flagName = lastArg[index-1 : index]
|
||||||
|
}
|
||||||
lastArg = lastArg[index+1:]
|
lastArg = lastArg[index+1:]
|
||||||
flagWithEqual = true
|
flagWithEqual = true
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -459,8 +519,16 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
|
||||||
// If the flag contains an = it means it has already been fully processed,
|
// If the flag contains an = it means it has already been fully processed,
|
||||||
// so we don't need to deal with it here.
|
// so we don't need to deal with it here.
|
||||||
if index := strings.Index(prevArg, "="); index < 0 {
|
if index := strings.Index(prevArg, "="); index < 0 {
|
||||||
flagName = strings.TrimLeft(prevArg, "-")
|
if strings.HasPrefix(prevArg, "--") {
|
||||||
|
// Flag has full name
|
||||||
|
flagName = prevArg[2:]
|
||||||
|
} else {
|
||||||
|
// Flag is shorthand
|
||||||
|
// We have to get the last shorthand flag name
|
||||||
|
// e.g. `-asd` => d to provide the correct completion
|
||||||
|
// https://github.com/spf13/cobra/issues/1257
|
||||||
|
flagName = prevArg[len(prevArg)-1:]
|
||||||
|
}
|
||||||
// Remove the uncompleted flag or else there could be an error created
|
// Remove the uncompleted flag or else there could be an error created
|
||||||
// for an invalid value for that flag
|
// for an invalid value for that flag
|
||||||
trimmedArgs = args[:len(args)-1]
|
trimmedArgs = args[:len(args)-1]
|
||||||
|
|
@ -476,9 +544,8 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
|
||||||
|
|
||||||
flag := findFlag(finalCmd, flagName)
|
flag := findFlag(finalCmd, flagName)
|
||||||
if flag == nil {
|
if flag == nil {
|
||||||
// Flag not supported by this command, nothing to complete
|
// Flag not supported by this command, the interspersed option might be set so return the original args
|
||||||
err := fmt.Errorf("Subcommand '%s' does not support flag '%s'", finalCmd.Name(), flagName)
|
return nil, args, orgLastArg, &flagCompError{subCommand: finalCmd.Name(), flagName: flagName}
|
||||||
return nil, nil, "", err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !flagWithEqual {
|
if !flagWithEqual {
|
||||||
|
|
@ -494,6 +561,156 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
|
||||||
return flag, trimmedArgs, lastArg, nil
|
return flag, trimmedArgs, lastArg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initDefaultCompletionCmd adds a default 'completion' command to c.
|
||||||
|
// This function will do nothing if any of the following is true:
|
||||||
|
// 1- the feature has been explicitly disabled by the program,
|
||||||
|
// 2- c has no subcommands (to avoid creating one),
|
||||||
|
// 3- c already has a 'completion' command provided by the program.
|
||||||
|
func (c *Command) initDefaultCompletionCmd() {
|
||||||
|
if c.CompletionOptions.DisableDefaultCmd || !c.HasSubCommands() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cmd := range c.commands {
|
||||||
|
if cmd.Name() == compCmdName || cmd.HasAlias(compCmdName) {
|
||||||
|
// A completion command is already available
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
haveNoDescFlag := !c.CompletionOptions.DisableNoDescFlag && !c.CompletionOptions.DisableDescriptions
|
||||||
|
|
||||||
|
completionCmd := &Command{
|
||||||
|
Use: compCmdName,
|
||||||
|
Short: "generate the autocompletion script for the specified shell",
|
||||||
|
Long: fmt.Sprintf(`
|
||||||
|
Generate the autocompletion script for %[1]s for the specified shell.
|
||||||
|
See each sub-command's help for details on how to use the generated script.
|
||||||
|
`, c.Root().Name()),
|
||||||
|
Args: NoArgs,
|
||||||
|
ValidArgsFunction: NoFileCompletions,
|
||||||
|
}
|
||||||
|
c.AddCommand(completionCmd)
|
||||||
|
|
||||||
|
out := c.OutOrStdout()
|
||||||
|
noDesc := c.CompletionOptions.DisableDescriptions
|
||||||
|
shortDesc := "generate the autocompletion script for %s"
|
||||||
|
bash := &Command{
|
||||||
|
Use: "bash",
|
||||||
|
Short: fmt.Sprintf(shortDesc, "bash"),
|
||||||
|
Long: fmt.Sprintf(`
|
||||||
|
Generate the autocompletion script for the bash shell.
|
||||||
|
|
||||||
|
This script depends on the 'bash-completion' package.
|
||||||
|
If it is not installed already, you can install it via your OS's package manager.
|
||||||
|
|
||||||
|
To load completions in your current shell session:
|
||||||
|
$ source <(%[1]s completion bash)
|
||||||
|
|
||||||
|
To load completions for every new session, execute once:
|
||||||
|
Linux:
|
||||||
|
$ %[1]s completion bash > /etc/bash_completion.d/%[1]s
|
||||||
|
MacOS:
|
||||||
|
$ %[1]s completion bash > /usr/local/etc/bash_completion.d/%[1]s
|
||||||
|
|
||||||
|
You will need to start a new shell for this setup to take effect.
|
||||||
|
`, c.Root().Name()),
|
||||||
|
Args: NoArgs,
|
||||||
|
DisableFlagsInUseLine: true,
|
||||||
|
ValidArgsFunction: NoFileCompletions,
|
||||||
|
RunE: func(cmd *Command, args []string) error {
|
||||||
|
return cmd.Root().GenBashCompletionV2(out, !noDesc)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if haveNoDescFlag {
|
||||||
|
bash.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
zsh := &Command{
|
||||||
|
Use: "zsh",
|
||||||
|
Short: fmt.Sprintf(shortDesc, "zsh"),
|
||||||
|
Long: fmt.Sprintf(`
|
||||||
|
Generate the autocompletion script for the zsh shell.
|
||||||
|
|
||||||
|
If shell completion is not already enabled in your environment you will need
|
||||||
|
to enable it. You can execute the following once:
|
||||||
|
|
||||||
|
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
|
||||||
|
|
||||||
|
To load completions for every new session, execute once:
|
||||||
|
# Linux:
|
||||||
|
$ %[1]s completion zsh > "${fpath[1]}/_%[1]s"
|
||||||
|
# macOS:
|
||||||
|
$ %[1]s completion zsh > /usr/local/share/zsh/site-functions/_%[1]s
|
||||||
|
|
||||||
|
You will need to start a new shell for this setup to take effect.
|
||||||
|
`, c.Root().Name()),
|
||||||
|
Args: NoArgs,
|
||||||
|
ValidArgsFunction: NoFileCompletions,
|
||||||
|
RunE: func(cmd *Command, args []string) error {
|
||||||
|
if noDesc {
|
||||||
|
return cmd.Root().GenZshCompletionNoDesc(out)
|
||||||
|
}
|
||||||
|
return cmd.Root().GenZshCompletion(out)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if haveNoDescFlag {
|
||||||
|
zsh.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
fish := &Command{
|
||||||
|
Use: "fish",
|
||||||
|
Short: fmt.Sprintf(shortDesc, "fish"),
|
||||||
|
Long: fmt.Sprintf(`
|
||||||
|
Generate the autocompletion script for the fish shell.
|
||||||
|
|
||||||
|
To load completions in your current shell session:
|
||||||
|
$ %[1]s completion fish | source
|
||||||
|
|
||||||
|
To load completions for every new session, execute once:
|
||||||
|
$ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish
|
||||||
|
|
||||||
|
You will need to start a new shell for this setup to take effect.
|
||||||
|
`, c.Root().Name()),
|
||||||
|
Args: NoArgs,
|
||||||
|
ValidArgsFunction: NoFileCompletions,
|
||||||
|
RunE: func(cmd *Command, args []string) error {
|
||||||
|
return cmd.Root().GenFishCompletion(out, !noDesc)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if haveNoDescFlag {
|
||||||
|
fish.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
powershell := &Command{
|
||||||
|
Use: "powershell",
|
||||||
|
Short: fmt.Sprintf(shortDesc, "powershell"),
|
||||||
|
Long: fmt.Sprintf(`
|
||||||
|
Generate the autocompletion script for powershell.
|
||||||
|
|
||||||
|
To load completions in your current shell session:
|
||||||
|
PS C:\> %[1]s completion powershell | Out-String | Invoke-Expression
|
||||||
|
|
||||||
|
To load completions for every new session, add the output of the above command
|
||||||
|
to your powershell profile.
|
||||||
|
`, c.Root().Name()),
|
||||||
|
Args: NoArgs,
|
||||||
|
ValidArgsFunction: NoFileCompletions,
|
||||||
|
RunE: func(cmd *Command, args []string) error {
|
||||||
|
if noDesc {
|
||||||
|
return cmd.Root().GenPowerShellCompletion(out)
|
||||||
|
}
|
||||||
|
return cmd.Root().GenPowerShellCompletionWithDesc(out)
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if haveNoDescFlag {
|
||||||
|
powershell.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
completionCmd.AddCommand(bash, zsh, fish, powershell)
|
||||||
|
}
|
||||||
|
|
||||||
func findFlag(cmd *Command, name string) *pflag.Flag {
|
func findFlag(cmd *Command, name string) *pflag.Flag {
|
||||||
flagSet := cmd.Flags()
|
flagSet := cmd.Flags()
|
||||||
if len(name) == 1 {
|
if len(name) == 1 {
|
||||||
|
|
@ -21,44 +21,47 @@ func genFishComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||||
WriteStringAndCheck(buf, fmt.Sprintf("# fish completion for %-36s -*- shell-script -*-\n", name))
|
WriteStringAndCheck(buf, fmt.Sprintf("# fish completion for %-36s -*- shell-script -*-\n", name))
|
||||||
WriteStringAndCheck(buf, fmt.Sprintf(`
|
WriteStringAndCheck(buf, fmt.Sprintf(`
|
||||||
function __%[1]s_debug
|
function __%[1]s_debug
|
||||||
set file "$BASH_COMP_DEBUG_FILE"
|
set -l file "$BASH_COMP_DEBUG_FILE"
|
||||||
if test -n "$file"
|
if test -n "$file"
|
||||||
echo "$argv" >> $file
|
echo "$argv" >> $file
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function __%[1]s_perform_completion
|
function __%[1]s_perform_completion
|
||||||
__%[1]s_debug "Starting __%[1]s_perform_completion with: $argv"
|
__%[1]s_debug "Starting __%[1]s_perform_completion"
|
||||||
|
|
||||||
set args (string split -- " " "$argv")
|
# Extract all args except the last one
|
||||||
set lastArg "$args[-1]"
|
set -l args (commandline -opc)
|
||||||
|
# Extract the last arg and escape it in case it is a space
|
||||||
|
set -l lastArg (string escape -- (commandline -ct))
|
||||||
|
|
||||||
__%[1]s_debug "args: $args"
|
__%[1]s_debug "args: $args"
|
||||||
__%[1]s_debug "last arg: $lastArg"
|
__%[1]s_debug "last arg: $lastArg"
|
||||||
|
|
||||||
set emptyArg ""
|
set -l requestComp "$args[1] %[3]s $args[2..-1] $lastArg"
|
||||||
if test -z "$lastArg"
|
|
||||||
__%[1]s_debug "Setting emptyArg"
|
|
||||||
set emptyArg \"\"
|
|
||||||
end
|
|
||||||
__%[1]s_debug "emptyArg: $emptyArg"
|
|
||||||
|
|
||||||
if not type -q "$args[1]"
|
|
||||||
# This can happen when "complete --do-complete %[2]s" is called when running this script.
|
|
||||||
__%[1]s_debug "Cannot find $args[1]. No completions."
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
set requestComp "$args[1] %[3]s $args[2..-1] $emptyArg"
|
|
||||||
__%[1]s_debug "Calling $requestComp"
|
__%[1]s_debug "Calling $requestComp"
|
||||||
|
set -l results (eval $requestComp 2> /dev/null)
|
||||||
|
|
||||||
set results (eval $requestComp 2> /dev/null)
|
# Some programs may output extra empty lines after the directive.
|
||||||
set comps $results[1..-2]
|
# Let's ignore them or else it will break completion.
|
||||||
set directiveLine $results[-1]
|
# Ref: https://github.com/spf13/cobra/issues/1279
|
||||||
|
for line in $results[-1..1]
|
||||||
|
if test (string trim -- $line) = ""
|
||||||
|
# Found an empty line, remove it
|
||||||
|
set results $results[1..-2]
|
||||||
|
else
|
||||||
|
# Found non-empty line, we have our proper output
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l comps $results[1..-2]
|
||||||
|
set -l directiveLine $results[-1]
|
||||||
|
|
||||||
# For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>)
|
# For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>)
|
||||||
# completions must be prefixed with the flag
|
# completions must be prefixed with the flag
|
||||||
set flagPrefix (string match -r -- '-.*=' "$lastArg")
|
set -l flagPrefix (string match -r -- '-.*=' "$lastArg")
|
||||||
|
|
||||||
__%[1]s_debug "Comps: $comps"
|
__%[1]s_debug "Comps: $comps"
|
||||||
__%[1]s_debug "DirectiveLine: $directiveLine"
|
__%[1]s_debug "DirectiveLine: $directiveLine"
|
||||||
|
|
@ -71,115 +74,124 @@ function __%[1]s_perform_completion
|
||||||
printf "%%s\n" "$directiveLine"
|
printf "%%s\n" "$directiveLine"
|
||||||
end
|
end
|
||||||
|
|
||||||
# This function does three things:
|
# This function does two things:
|
||||||
# 1- Obtain the completions and store them in the global __%[1]s_comp_results
|
# - Obtain the completions and store them in the global __%[1]s_comp_results
|
||||||
# 2- Set the __%[1]s_comp_do_file_comp flag if file completion should be performed
|
# - Return false if file completion should be performed
|
||||||
# and unset it otherwise
|
|
||||||
# 3- Return true if the completion results are not empty
|
|
||||||
function __%[1]s_prepare_completions
|
function __%[1]s_prepare_completions
|
||||||
|
__%[1]s_debug ""
|
||||||
|
__%[1]s_debug "========= starting completion logic =========="
|
||||||
|
|
||||||
# Start fresh
|
# Start fresh
|
||||||
set --erase __%[1]s_comp_do_file_comp
|
|
||||||
set --erase __%[1]s_comp_results
|
set --erase __%[1]s_comp_results
|
||||||
|
|
||||||
# Check if the command-line is already provided. This is useful for testing.
|
set -l results (__%[1]s_perform_completion)
|
||||||
if not set --query __%[1]s_comp_commandLine
|
|
||||||
# Use the -c flag to allow for completion in the middle of the line
|
|
||||||
set __%[1]s_comp_commandLine (commandline -c)
|
|
||||||
end
|
|
||||||
__%[1]s_debug "commandLine is: $__%[1]s_comp_commandLine"
|
|
||||||
|
|
||||||
set results (__%[1]s_perform_completion "$__%[1]s_comp_commandLine")
|
|
||||||
set --erase __%[1]s_comp_commandLine
|
|
||||||
__%[1]s_debug "Completion results: $results"
|
__%[1]s_debug "Completion results: $results"
|
||||||
|
|
||||||
if test -z "$results"
|
if test -z "$results"
|
||||||
__%[1]s_debug "No completion, probably due to a failure"
|
__%[1]s_debug "No completion, probably due to a failure"
|
||||||
# Might as well do file completion, in case it helps
|
# Might as well do file completion, in case it helps
|
||||||
set --global __%[1]s_comp_do_file_comp 1
|
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
set directive (string sub --start 2 $results[-1])
|
set -l directive (string sub --start 2 $results[-1])
|
||||||
set --global __%[1]s_comp_results $results[1..-2]
|
set --global __%[1]s_comp_results $results[1..-2]
|
||||||
|
|
||||||
__%[1]s_debug "Completions are: $__%[1]s_comp_results"
|
__%[1]s_debug "Completions are: $__%[1]s_comp_results"
|
||||||
__%[1]s_debug "Directive is: $directive"
|
__%[1]s_debug "Directive is: $directive"
|
||||||
|
|
||||||
set shellCompDirectiveError %[4]d
|
set -l shellCompDirectiveError %[4]d
|
||||||
set shellCompDirectiveNoSpace %[5]d
|
set -l shellCompDirectiveNoSpace %[5]d
|
||||||
set shellCompDirectiveNoFileComp %[6]d
|
set -l shellCompDirectiveNoFileComp %[6]d
|
||||||
set shellCompDirectiveFilterFileExt %[7]d
|
set -l shellCompDirectiveFilterFileExt %[7]d
|
||||||
set shellCompDirectiveFilterDirs %[8]d
|
set -l shellCompDirectiveFilterDirs %[8]d
|
||||||
|
|
||||||
if test -z "$directive"
|
if test -z "$directive"
|
||||||
set directive 0
|
set directive 0
|
||||||
end
|
end
|
||||||
|
|
||||||
set compErr (math (math --scale 0 $directive / $shellCompDirectiveError) %% 2)
|
set -l compErr (math (math --scale 0 $directive / $shellCompDirectiveError) %% 2)
|
||||||
if test $compErr -eq 1
|
if test $compErr -eq 1
|
||||||
__%[1]s_debug "Received error directive: aborting."
|
__%[1]s_debug "Received error directive: aborting."
|
||||||
# Might as well do file completion, in case it helps
|
# Might as well do file completion, in case it helps
|
||||||
set --global __%[1]s_comp_do_file_comp 1
|
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
set filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) %% 2)
|
set -l filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) %% 2)
|
||||||
set dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) %% 2)
|
set -l dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) %% 2)
|
||||||
if test $filefilter -eq 1; or test $dirfilter -eq 1
|
if test $filefilter -eq 1; or test $dirfilter -eq 1
|
||||||
__%[1]s_debug "File extension filtering or directory filtering not supported"
|
__%[1]s_debug "File extension filtering or directory filtering not supported"
|
||||||
# Do full file completion instead
|
# Do full file completion instead
|
||||||
set --global __%[1]s_comp_do_file_comp 1
|
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
set nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) %% 2)
|
set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) %% 2)
|
||||||
set nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) %% 2)
|
set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) %% 2)
|
||||||
|
|
||||||
__%[1]s_debug "nospace: $nospace, nofiles: $nofiles"
|
__%[1]s_debug "nospace: $nospace, nofiles: $nofiles"
|
||||||
|
|
||||||
|
# If we want to prevent a space, or if file completion is NOT disabled,
|
||||||
|
# we need to count the number of valid completions.
|
||||||
|
# To do so, we will filter on prefix as the completions we have received
|
||||||
|
# may not already be filtered so as to allow fish to match on different
|
||||||
|
# criteria than the prefix.
|
||||||
|
if test $nospace -ne 0; or test $nofiles -eq 0
|
||||||
|
set -l prefix (commandline -t | string escape --style=regex)
|
||||||
|
__%[1]s_debug "prefix: $prefix"
|
||||||
|
|
||||||
|
set -l completions (string match -r -- "^$prefix.*" $__%[1]s_comp_results)
|
||||||
|
set --global __%[1]s_comp_results $completions
|
||||||
|
__%[1]s_debug "Filtered completions are: $__%[1]s_comp_results"
|
||||||
|
|
||||||
# Important not to quote the variable for count to work
|
# Important not to quote the variable for count to work
|
||||||
set numComps (count $__%[1]s_comp_results)
|
set -l numComps (count $__%[1]s_comp_results)
|
||||||
__%[1]s_debug "numComps: $numComps"
|
__%[1]s_debug "numComps: $numComps"
|
||||||
|
|
||||||
if test $numComps -eq 1; and test $nospace -ne 0
|
if test $numComps -eq 1; and test $nospace -ne 0
|
||||||
# To support the "nospace" directive we trick the shell
|
# We must first split on \t to get rid of the descriptions to be
|
||||||
|
# able to check what the actual completion will be.
|
||||||
|
# We don't need descriptions anyway since there is only a single
|
||||||
|
# real completion which the shell will expand immediately.
|
||||||
|
set -l split (string split --max 1 \t $__%[1]s_comp_results[1])
|
||||||
|
|
||||||
|
# Fish won't add a space if the completion ends with any
|
||||||
|
# of the following characters: @=/:.,
|
||||||
|
set -l lastChar (string sub -s -1 -- $split)
|
||||||
|
if not string match -r -q "[@=/:.,]" -- "$lastChar"
|
||||||
|
# In other cases, to support the "nospace" directive we trick the shell
|
||||||
# by outputting an extra, longer completion.
|
# by outputting an extra, longer completion.
|
||||||
__%[1]s_debug "Adding second completion to perform nospace directive"
|
__%[1]s_debug "Adding second completion to perform nospace directive"
|
||||||
set --append __%[1]s_comp_results $__%[1]s_comp_results[1].
|
set --global __%[1]s_comp_results $split[1] $split[1].
|
||||||
|
__%[1]s_debug "Completions are now: $__%[1]s_comp_results"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if test $numComps -eq 0; and test $nofiles -eq 0
|
if test $numComps -eq 0; and test $nofiles -eq 0
|
||||||
|
# To be consistent with bash and zsh, we only trigger file
|
||||||
|
# completion when there are no other completions
|
||||||
__%[1]s_debug "Requesting file completion"
|
__%[1]s_debug "Requesting file completion"
|
||||||
set --global __%[1]s_comp_do_file_comp 1
|
return 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# If we don't want file completion, we must return true even if there
|
return 0
|
||||||
# are no completions found. This is because fish will perform the last
|
|
||||||
# completion command, even if its condition is false, if no other
|
|
||||||
# completion command was triggered
|
|
||||||
return (not set --query __%[1]s_comp_do_file_comp)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Since Fish completions are only loaded once the user triggers them, we trigger them ourselves
|
# Since Fish completions are only loaded once the user triggers them, we trigger them ourselves
|
||||||
# so we can properly delete any completions provided by another script.
|
# so we can properly delete any completions provided by another script.
|
||||||
# The space after the the program name is essential to trigger completion for the program
|
# Only do this if the program can be found, or else fish may print some errors; besides,
|
||||||
|
# the existing completions will only be loaded if the program can be found.
|
||||||
|
if type -q "%[2]s"
|
||||||
|
# The space after the program name is essential to trigger completion for the program
|
||||||
# and not completion of the program name itself.
|
# and not completion of the program name itself.
|
||||||
|
# Also, we use '> /dev/null 2>&1' since '&>' is not supported in older versions of fish.
|
||||||
complete --do-complete "%[2]s " > /dev/null 2>&1
|
complete --do-complete "%[2]s " > /dev/null 2>&1
|
||||||
# Using '> /dev/null 2>&1' since '&>' is not supported in older versions of fish.
|
end
|
||||||
|
|
||||||
# Remove any pre-existing completions for the program since we will be handling all of them.
|
# Remove any pre-existing completions for the program since we will be handling all of them.
|
||||||
complete -c %[2]s -e
|
complete -c %[2]s -e
|
||||||
|
|
||||||
# The order in which the below two lines are defined is very important so that __%[1]s_prepare_completions
|
# The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results
|
||||||
# is called first. It is __%[1]s_prepare_completions that sets up the __%[1]s_comp_do_file_comp variable.
|
# which provides the program's completion choices.
|
||||||
#
|
|
||||||
# This completion will be run second as complete commands are added FILO.
|
|
||||||
# It triggers file completion choices when __%[1]s_comp_do_file_comp is set.
|
|
||||||
complete -c %[2]s -n 'set --query __%[1]s_comp_do_file_comp'
|
|
||||||
|
|
||||||
# This completion will be run first as complete commands are added FILO.
|
|
||||||
# The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results and __%[1]s_comp_do_file_comp.
|
|
||||||
# It provides the program's completion choices.
|
|
||||||
complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
||||||
|
|
||||||
`, nameForVar, name, compCmd,
|
`, nameForVar, name, compCmd,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
module github.com/spf13/cobra
|
module github.com/spf13/cobra
|
||||||
|
|
||||||
go 1.12
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0
|
github.com/cpuguy83/go-md2man/v2 v2.0.0
|
||||||
github.com/inconshreveable/mousetrap v1.0.0
|
github.com/inconshreveable/mousetrap v1.0.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.7.0
|
github.com/spf13/viper v1.8.1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -5,74 +5,141 @@ cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6A
|
||||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
|
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||||
|
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||||
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
|
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||||
|
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||||
|
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.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||||
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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||||
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
|
||||||
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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
|
||||||
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/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=
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
|
||||||
github.com/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.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
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/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||||
|
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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
|
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||||
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree 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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
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-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
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/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
|
||||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
|
@ -94,61 +161,50 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
|
||||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
|
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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||||
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/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=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
|
||||||
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 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
||||||
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/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=
|
||||||
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
|
@ -156,49 +212,65 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
|
||||||
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/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
|
||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
|
||||||
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.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
|
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
|
||||||
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/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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
github.com/yuin/goldmark v1.1.32/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=
|
||||||
|
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||||
|
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||||
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.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
|
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||||
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
|
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
|
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
|
@ -208,16 +280,26 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/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.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
|
@ -226,35 +308,107 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
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=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/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-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/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=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/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-20210220032951-036812b2e83c/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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
|
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/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-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/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-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||||
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
|
@ -264,6 +418,7 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
|
@ -271,16 +426,73 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
|
||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||||
|
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
|
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
|
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||||
|
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.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||||
|
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
||||||
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=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
|
@ -290,24 +502,91 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/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-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-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||||
|
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
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.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
|
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
|
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||||
|
google.golang.org/grpc v1.35.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.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
|
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/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
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=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
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-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,25 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
|
||||||
$Space = ""
|
$Space = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or
|
||||||
|
(($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) {
|
||||||
|
__%[1]s_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported"
|
||||||
|
|
||||||
|
# return here to prevent the completion of the extensions
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$Values = $Values | Where-Object {
|
||||||
|
# filter the result
|
||||||
|
$_.Name -like "$WordToComplete*"
|
||||||
|
|
||||||
|
# Join the flag back if we have an equal sign flag
|
||||||
|
if ( $IsEqualFlag ) {
|
||||||
|
__%[1]s_debug "Join the equal sign flag back to the completion value"
|
||||||
|
$_.Name = $Flag + "=" + $_.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
|
if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
|
||||||
__%[1]s_debug "ShellCompDirectiveNoFileComp is called"
|
__%[1]s_debug "ShellCompDirectiveNoFileComp is called"
|
||||||
|
|
||||||
|
|
@ -153,32 +172,13 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or
|
|
||||||
(($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) {
|
|
||||||
__%[1]s_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported"
|
|
||||||
|
|
||||||
# return here to prevent the completion of the extensions
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$Values = $Values | Where-Object {
|
|
||||||
# filter the result
|
|
||||||
$_.Name -like "$WordToComplete*"
|
|
||||||
|
|
||||||
# Join the flag back if we have a equal sign flag
|
|
||||||
if ( $IsEqualFlag ) {
|
|
||||||
__%[1]s_debug "Join the equal sign flag back to the completion value"
|
|
||||||
$_.Name = $Flag + "=" + $_.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get the current mode
|
# Get the current mode
|
||||||
$Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function
|
$Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function
|
||||||
__%[1]s_debug "Mode: $Mode"
|
__%[1]s_debug "Mode: $Mode"
|
||||||
|
|
||||||
$Values | ForEach-Object {
|
$Values | ForEach-Object {
|
||||||
|
|
||||||
# store temporay because switch will overwrite $_
|
# store temporary because switch will overwrite $_
|
||||||
$comp = $_
|
$comp = $_
|
||||||
|
|
||||||
# PowerShell supports three different completion modes
|
# PowerShell supports three different completion modes
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,15 @@ The currently supported shells are:
|
||||||
- fish
|
- fish
|
||||||
- PowerShell
|
- PowerShell
|
||||||
|
|
||||||
|
Cobra will automatically provide your program with a fully functional `completion` command,
|
||||||
|
similarly to how it provides the `help` command.
|
||||||
|
|
||||||
|
## Creating your own completion command
|
||||||
|
|
||||||
|
If you do not wish to use the default `completion` command, you can choose to
|
||||||
|
provide your own, which will take precedence over the default one. (This also provides
|
||||||
|
backwards-compatibility with programs that already have their own `completion` command.)
|
||||||
|
|
||||||
If you are using the generator, you can create a completion command by running
|
If you are using the generator, you can create a completion command by running
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -70,7 +79,7 @@ PowerShell:
|
||||||
case "fish":
|
case "fish":
|
||||||
cmd.Root().GenFishCompletion(os.Stdout, true)
|
cmd.Root().GenFishCompletion(os.Stdout, true)
|
||||||
case "powershell":
|
case "powershell":
|
||||||
cmd.Root().GenPowerShellCompletion(os.Stdout)
|
cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -78,6 +87,26 @@ PowerShell:
|
||||||
|
|
||||||
**Note:** The cobra generator may include messages printed to stdout, for example, if the config file is loaded; this will break the auto-completion script so must be removed.
|
**Note:** The cobra generator may include messages printed to stdout, for example, if the config file is loaded; this will break the auto-completion script so must be removed.
|
||||||
|
|
||||||
|
## Adapting the default completion command
|
||||||
|
|
||||||
|
Cobra provides a few options for the default `completion` command. To configure such options you must set
|
||||||
|
the `CompletionOptions` field on the *root* command.
|
||||||
|
|
||||||
|
To tell Cobra *not* to provide the default `completion` command:
|
||||||
|
```
|
||||||
|
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||||
|
```
|
||||||
|
|
||||||
|
To tell Cobra *not* to provide the user with the `--no-descriptions` flag to the completion sub-commands:
|
||||||
|
```
|
||||||
|
rootCmd.CompletionOptions.DisableNoDescFlag = true
|
||||||
|
```
|
||||||
|
|
||||||
|
To tell Cobra to completely disable descriptions for completions:
|
||||||
|
```
|
||||||
|
rootCmd.CompletionOptions.DisableDescriptions = true
|
||||||
|
```
|
||||||
|
|
||||||
# Customizing completions
|
# Customizing completions
|
||||||
|
|
||||||
The generated completion scripts will automatically handle completing commands and flags. However, you can make your completions much more powerful by providing information to complete your program's nouns and flag values.
|
The generated completion scripts will automatically handle completing commands and flags. However, you can make your completions much more powerful by providing information to complete your program's nouns and flag values.
|
||||||
|
|
@ -323,7 +352,10 @@ cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string,
|
||||||
```
|
```
|
||||||
### Descriptions for completions
|
### Descriptions for completions
|
||||||
|
|
||||||
`zsh`, `fish` and `powershell` allow for descriptions to annotate completion choices. For commands and flags, Cobra will provide the descriptions automatically, based on usage information. For example, using zsh:
|
Cobra provides support for completion descriptions. Such descriptions are supported for each shell
|
||||||
|
(however, for bash, it is only available in the [completion V2 version](#bash-completion-v2)).
|
||||||
|
For commands and flags, Cobra will provide the descriptions automatically, based on usage information.
|
||||||
|
For example, using zsh:
|
||||||
```
|
```
|
||||||
$ helm s[tab]
|
$ helm s[tab]
|
||||||
search -- search for a keyword in charts
|
search -- search for a keyword in charts
|
||||||
|
|
@ -336,7 +368,7 @@ $ helm s[tab]
|
||||||
search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release)
|
search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release)
|
||||||
```
|
```
|
||||||
|
|
||||||
Cobra allows you to add annotations to your own completions. Simply add the annotation text after each completion, following a `\t` separator. This technique applies to completions returned by `ValidArgs`, `ValidArgsFunction` and `RegisterFlagCompletionFunc()`. For example:
|
Cobra allows you to add descriptions to your own completions. Simply add the description text after each completion, following a `\t` separator. This technique applies to completions returned by `ValidArgs`, `ValidArgsFunction` and `RegisterFlagCompletionFunc()`. For example:
|
||||||
```go
|
```go
|
||||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
return []string{"harbor\tAn image registry", "thanos\tLong-term metrics"}, cobra.ShellCompDirectiveNoFileComp
|
return []string{"harbor\tAn image registry", "thanos\tLong-term metrics"}, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
|
@ -371,6 +403,37 @@ completion firstcommand secondcommand
|
||||||
For backward compatibility, Cobra still supports its bash legacy dynamic completion solution.
|
For backward compatibility, Cobra still supports its bash legacy dynamic completion solution.
|
||||||
Please refer to [Bash Completions](bash_completions.md) for details.
|
Please refer to [Bash Completions](bash_completions.md) for details.
|
||||||
|
|
||||||
|
### Bash completion V2
|
||||||
|
|
||||||
|
Cobra provides two versions for bash completion. The original bash completion (which started it all!) can be used by calling
|
||||||
|
`GenBashCompletion()` or `GenBashCompletionFile()`.
|
||||||
|
|
||||||
|
A new V2 bash completion version is also available. This version can be used by calling `GenBashCompletionV2()` or
|
||||||
|
`GenBashCompletionFileV2()`. The V2 version does **not** support the legacy dynamic completion
|
||||||
|
(see [Bash Completions](bash_completions.md)) but instead works only with the Go dynamic completion
|
||||||
|
solution described in this document.
|
||||||
|
Unless your program already uses the legacy dynamic completion solution, it is recommended that you use the bash
|
||||||
|
completion V2 solution which provides the following extra features:
|
||||||
|
- Supports completion descriptions (like the other shells)
|
||||||
|
- Small completion script of less than 300 lines (v1 generates scripts of thousands of lines; `kubectl` for example has a bash v1 completion script of over 13K lines)
|
||||||
|
- Streamlined user experience thanks to a completion behavior aligned with the other shells
|
||||||
|
|
||||||
|
`Bash` completion V2 supports descriptions for completions. When calling `GenBashCompletionV2()` or `GenBashCompletionFileV2()`
|
||||||
|
you must provide these functions with a parameter indicating if the completions should be annotated with a description; Cobra
|
||||||
|
will provide the description automatically based on usage information. You can choose to make this option configurable by
|
||||||
|
your users.
|
||||||
|
|
||||||
|
```
|
||||||
|
# With descriptions
|
||||||
|
$ helm s[tab][tab]
|
||||||
|
search (search for a keyword in charts) status (display the status of the named release)
|
||||||
|
show (show information of a chart)
|
||||||
|
|
||||||
|
# Without descriptions
|
||||||
|
$ helm s[tab][tab]
|
||||||
|
search show status
|
||||||
|
```
|
||||||
|
**Note**: Cobra's default `completion` command uses bash completion V2. If for some reason you need to use bash completion V1, you will need to implement your own `completion` command.
|
||||||
## Zsh completions
|
## Zsh completions
|
||||||
|
|
||||||
Cobra supports native zsh completion generated from the root `cobra.Command`.
|
Cobra supports native zsh completion generated from the root `cobra.Command`.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,637 @@
|
||||||
|
# User Guide
|
||||||
|
|
||||||
|
While you are welcome to provide your own organization, typically a Cobra-based
|
||||||
|
application will follow the following organizational structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
▾ appName/
|
||||||
|
▾ cmd/
|
||||||
|
add.go
|
||||||
|
your.go
|
||||||
|
commands.go
|
||||||
|
here.go
|
||||||
|
main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"{pathToYourApp}/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd.Execute()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using the Cobra Generator
|
||||||
|
|
||||||
|
Cobra provides its own program that will create your application and add any
|
||||||
|
commands you want. It's the easiest way to incorporate Cobra into your application.
|
||||||
|
|
||||||
|
[Here](https://github.com/spf13/cobra/blob/master/cobra/README.md) you can find more information about it.
|
||||||
|
|
||||||
|
## Using the Cobra Library
|
||||||
|
|
||||||
|
To manually implement Cobra you need to create a bare main.go file and a rootCmd file.
|
||||||
|
You will optionally provide additional commands as you see fit.
|
||||||
|
|
||||||
|
### Create rootCmd
|
||||||
|
|
||||||
|
Cobra doesn't require any special constructors. Simply create your commands.
|
||||||
|
|
||||||
|
Ideally you place this in app/cmd/root.go:
|
||||||
|
|
||||||
|
```go
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "hugo",
|
||||||
|
Short: "Hugo is a very fast static site generator",
|
||||||
|
Long: `A Fast and Flexible Static Site Generator built with
|
||||||
|
love by spf13 and friends in Go.
|
||||||
|
Complete documentation is available at http://hugo.spf13.com`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
// Do Stuff Here
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execute() {
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You will additionally define flags and handle configuration in your init() function.
|
||||||
|
|
||||||
|
For example cmd/root.go:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Used for flags.
|
||||||
|
cfgFile string
|
||||||
|
userLicense string
|
||||||
|
|
||||||
|
rootCmd = &cobra.Command{
|
||||||
|
Use: "cobra",
|
||||||
|
Short: "A generator for Cobra based Applications",
|
||||||
|
Long: `Cobra is a CLI library for Go that empowers applications.
|
||||||
|
This application is a tool to generate the needed files
|
||||||
|
to quickly create a Cobra application.`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Execute executes the root command.
|
||||||
|
func Execute() error {
|
||||||
|
return rootCmd.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cobra.OnInitialize(initConfig)
|
||||||
|
|
||||||
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
||||||
|
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
|
||||||
|
rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
|
||||||
|
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
||||||
|
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
|
||||||
|
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
||||||
|
viper.SetDefault("license", "apache")
|
||||||
|
|
||||||
|
rootCmd.AddCommand(addCmd)
|
||||||
|
rootCmd.AddCommand(initCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initConfig() {
|
||||||
|
if cfgFile != "" {
|
||||||
|
// Use config file from the flag.
|
||||||
|
viper.SetConfigFile(cfgFile)
|
||||||
|
} else {
|
||||||
|
// Find home directory.
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
cobra.CheckErr(err)
|
||||||
|
|
||||||
|
// Search config in home directory with name ".cobra" (without extension).
|
||||||
|
viper.AddConfigPath(home)
|
||||||
|
viper.SetConfigType("yaml")
|
||||||
|
viper.SetConfigName(".cobra")
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.AutomaticEnv()
|
||||||
|
|
||||||
|
if err := viper.ReadInConfig(); err == nil {
|
||||||
|
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create your main.go
|
||||||
|
|
||||||
|
With the root command you need to have your main function execute it.
|
||||||
|
Execute should be run on the root for clarity, though it can be called on any command.
|
||||||
|
|
||||||
|
In a Cobra app, typically the main.go file is very bare. It serves one purpose: to initialize Cobra.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"{pathToYourApp}/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd.Execute()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create additional commands
|
||||||
|
|
||||||
|
Additional commands can be defined and typically are each given their own file
|
||||||
|
inside of the cmd/ directory.
|
||||||
|
|
||||||
|
If you wanted to create a version command you would create cmd/version.go and
|
||||||
|
populate it with the following:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(versionCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
var versionCmd = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Print the version number of Hugo",
|
||||||
|
Long: `All software has versions. This is Hugo's`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Returning and handling errors
|
||||||
|
|
||||||
|
If you wish to return an error to the caller of a command, `RunE` can be used.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(tryCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tryCmd = &cobra.Command{
|
||||||
|
Use: "try",
|
||||||
|
Short: "Try and possibly fail at something",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if err := someFunc(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The error can then be caught at the execute function call.
|
||||||
|
|
||||||
|
## Working with Flags
|
||||||
|
|
||||||
|
Flags provide modifiers to control how the action command operates.
|
||||||
|
|
||||||
|
### Assign flags to a command
|
||||||
|
|
||||||
|
Since the flags are defined and used in different locations, we need to
|
||||||
|
define a variable outside with the correct scope to assign the flag to
|
||||||
|
work with.
|
||||||
|
|
||||||
|
```go
|
||||||
|
var Verbose bool
|
||||||
|
var Source string
|
||||||
|
```
|
||||||
|
|
||||||
|
There are two different approaches to assign a flag.
|
||||||
|
|
||||||
|
### Persistent Flags
|
||||||
|
|
||||||
|
A flag can be 'persistent', meaning that this flag will be available to the
|
||||||
|
command it's assigned to as well as every command under that command. For
|
||||||
|
global flags, assign a flag as a persistent flag on the root.
|
||||||
|
|
||||||
|
```go
|
||||||
|
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local Flags
|
||||||
|
|
||||||
|
A flag can also be assigned locally, which will only apply to that specific command.
|
||||||
|
|
||||||
|
```go
|
||||||
|
localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local Flag on Parent Commands
|
||||||
|
|
||||||
|
By default, Cobra only parses local flags on the target command, and any local flags on
|
||||||
|
parent commands are ignored. By enabling `Command.TraverseChildren`, Cobra will
|
||||||
|
parse local flags on each command before executing the target command.
|
||||||
|
|
||||||
|
```go
|
||||||
|
command := cobra.Command{
|
||||||
|
Use: "print [OPTIONS] [COMMANDS]",
|
||||||
|
TraverseChildren: true,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bind Flags with Config
|
||||||
|
|
||||||
|
You can also bind your flags with [viper](https://github.com/spf13/viper):
|
||||||
|
```go
|
||||||
|
var author string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
|
||||||
|
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the persistent flag `author` is bound with `viper`.
|
||||||
|
**Note**: the variable `author` will not be set to the value from config,
|
||||||
|
when the `--author` flag is not provided by user.
|
||||||
|
|
||||||
|
More in [viper documentation](https://github.com/spf13/viper#working-with-flags).
|
||||||
|
|
||||||
|
### Required flags
|
||||||
|
|
||||||
|
Flags are optional by default. If instead you wish your command to report an error
|
||||||
|
when a flag has not been set, mark it as required:
|
||||||
|
```go
|
||||||
|
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
|
||||||
|
rootCmd.MarkFlagRequired("region")
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, for persistent flags:
|
||||||
|
```go
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
|
||||||
|
rootCmd.MarkPersistentFlagRequired("region")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Positional and Custom Arguments
|
||||||
|
|
||||||
|
Validation of positional arguments can be specified using the `Args` field
|
||||||
|
of `Command`.
|
||||||
|
|
||||||
|
The following validators are built in:
|
||||||
|
|
||||||
|
- `NoArgs` - the command will report an error if there are any positional args.
|
||||||
|
- `ArbitraryArgs` - the command will accept any args.
|
||||||
|
- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`.
|
||||||
|
- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args.
|
||||||
|
- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args.
|
||||||
|
- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args.
|
||||||
|
- `ExactValidArgs(int)` - the command will report an error if there are not exactly N positional args OR if there are any positional args that are not in the `ValidArgs` field of `Command`
|
||||||
|
- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args.
|
||||||
|
|
||||||
|
An example of setting the custom validator:
|
||||||
|
|
||||||
|
```go
|
||||||
|
var cmd = &cobra.Command{
|
||||||
|
Short: "hello",
|
||||||
|
Args: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) < 1 {
|
||||||
|
return errors.New("requires a color argument")
|
||||||
|
}
|
||||||
|
if myapp.IsValidColor(args[0]) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("invalid color specified: %s", args[0])
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("Hello, World!")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
In the example below, we have defined three commands. Two are at the top level
|
||||||
|
and one (cmdTimes) is a child of one of the top commands. In this case the root
|
||||||
|
is not executable, meaning that a subcommand is required. This is accomplished
|
||||||
|
by not providing a 'Run' for the 'rootCmd'.
|
||||||
|
|
||||||
|
We have only defined one flag for a single command.
|
||||||
|
|
||||||
|
More documentation about flags is available at https://github.com/spf13/pflag
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var echoTimes int
|
||||||
|
|
||||||
|
var cmdPrint = &cobra.Command{
|
||||||
|
Use: "print [string to print]",
|
||||||
|
Short: "Print anything to the screen",
|
||||||
|
Long: `print is for printing anything back to the screen.
|
||||||
|
For many years people have printed back to the screen.`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("Print: " + strings.Join(args, " "))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdEcho = &cobra.Command{
|
||||||
|
Use: "echo [string to echo]",
|
||||||
|
Short: "Echo anything to the screen",
|
||||||
|
Long: `echo is for echoing anything back.
|
||||||
|
Echo works a lot like print, except it has a child command.`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("Echo: " + strings.Join(args, " "))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdTimes = &cobra.Command{
|
||||||
|
Use: "times [string to echo]",
|
||||||
|
Short: "Echo anything to the screen more times",
|
||||||
|
Long: `echo things multiple times back to the user by providing
|
||||||
|
a count and a string.`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
for i := 0; i < echoTimes; i++ {
|
||||||
|
fmt.Println("Echo: " + strings.Join(args, " "))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input")
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{Use: "app"}
|
||||||
|
rootCmd.AddCommand(cmdPrint, cmdEcho)
|
||||||
|
cmdEcho.AddCommand(cmdTimes)
|
||||||
|
rootCmd.Execute()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/).
|
||||||
|
|
||||||
|
## Help Command
|
||||||
|
|
||||||
|
Cobra automatically adds a help command to your application when you have subcommands.
|
||||||
|
This will be called when a user runs 'app help'. Additionally, help will also
|
||||||
|
support all other commands as input. Say, for instance, you have a command called
|
||||||
|
'create' without any additional configuration; Cobra will work when 'app help
|
||||||
|
create' is called. Every command will automatically have the '--help' flag added.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
The following output is automatically generated by Cobra. Nothing beyond the
|
||||||
|
command and flag definitions are needed.
|
||||||
|
|
||||||
|
$ cobra help
|
||||||
|
|
||||||
|
Cobra is a CLI library for Go that empowers applications.
|
||||||
|
This application is a tool to generate the needed files
|
||||||
|
to quickly create a Cobra application.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
cobra [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
add Add a command to a Cobra Application
|
||||||
|
help Help about any command
|
||||||
|
init Initialize a Cobra Application
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-a, --author string author name for copyright attribution (default "YOUR NAME")
|
||||||
|
--config string config file (default is $HOME/.cobra.yaml)
|
||||||
|
-h, --help help for cobra
|
||||||
|
-l, --license string name of license for the project
|
||||||
|
--viper use Viper for configuration (default true)
|
||||||
|
|
||||||
|
Use "cobra [command] --help" for more information about a command.
|
||||||
|
|
||||||
|
|
||||||
|
Help is just a command like any other. There is no special logic or behavior
|
||||||
|
around it. In fact, you can provide your own if you want.
|
||||||
|
|
||||||
|
### Defining your own help
|
||||||
|
|
||||||
|
You can provide your own Help command or your own template for the default command to use
|
||||||
|
with following functions:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cmd.SetHelpCommand(cmd *Command)
|
||||||
|
cmd.SetHelpFunc(f func(*Command, []string))
|
||||||
|
cmd.SetHelpTemplate(s string)
|
||||||
|
```
|
||||||
|
|
||||||
|
The latter two will also apply to any children commands.
|
||||||
|
|
||||||
|
## Usage Message
|
||||||
|
|
||||||
|
When the user provides an invalid flag or invalid command, Cobra responds by
|
||||||
|
showing the user the 'usage'.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
You may recognize this from the help above. That's because the default help
|
||||||
|
embeds the usage as part of its output.
|
||||||
|
|
||||||
|
$ cobra --invalid
|
||||||
|
Error: unknown flag: --invalid
|
||||||
|
Usage:
|
||||||
|
cobra [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
add Add a command to a Cobra Application
|
||||||
|
help Help about any command
|
||||||
|
init Initialize a Cobra Application
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-a, --author string author name for copyright attribution (default "YOUR NAME")
|
||||||
|
--config string config file (default is $HOME/.cobra.yaml)
|
||||||
|
-h, --help help for cobra
|
||||||
|
-l, --license string name of license for the project
|
||||||
|
--viper use Viper for configuration (default true)
|
||||||
|
|
||||||
|
Use "cobra [command] --help" for more information about a command.
|
||||||
|
|
||||||
|
### Defining your own usage
|
||||||
|
You can provide your own usage function or template for Cobra to use.
|
||||||
|
Like help, the function and template are overridable through public methods:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cmd.SetUsageFunc(f func(*Command) error)
|
||||||
|
cmd.SetUsageTemplate(s string)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Version Flag
|
||||||
|
|
||||||
|
Cobra adds a top-level '--version' flag if the Version field is set on the root command.
|
||||||
|
Running an application with the '--version' flag will print the version to stdout using
|
||||||
|
the version template. The template can be customized using the
|
||||||
|
`cmd.SetVersionTemplate(s string)` function.
|
||||||
|
|
||||||
|
## PreRun and PostRun Hooks
|
||||||
|
|
||||||
|
It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order:
|
||||||
|
|
||||||
|
- `PersistentPreRun`
|
||||||
|
- `PreRun`
|
||||||
|
- `Run`
|
||||||
|
- `PostRun`
|
||||||
|
- `PersistentPostRun`
|
||||||
|
|
||||||
|
An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "root [sub]",
|
||||||
|
Short: "My root command",
|
||||||
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args)
|
||||||
|
},
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside rootCmd PreRun with args: %v\n", args)
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside rootCmd Run with args: %v\n", args)
|
||||||
|
},
|
||||||
|
PostRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside rootCmd PostRun with args: %v\n", args)
|
||||||
|
},
|
||||||
|
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var subCmd = &cobra.Command{
|
||||||
|
Use: "sub [no options!]",
|
||||||
|
Short: "My subcommand",
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside subCmd PreRun with args: %v\n", args)
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside subCmd Run with args: %v\n", args)
|
||||||
|
},
|
||||||
|
PostRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside subCmd PostRun with args: %v\n", args)
|
||||||
|
},
|
||||||
|
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.AddCommand(subCmd)
|
||||||
|
|
||||||
|
rootCmd.SetArgs([]string{""})
|
||||||
|
rootCmd.Execute()
|
||||||
|
fmt.Println()
|
||||||
|
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
|
||||||
|
rootCmd.Execute()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
```
|
||||||
|
Inside rootCmd PersistentPreRun with args: []
|
||||||
|
Inside rootCmd PreRun with args: []
|
||||||
|
Inside rootCmd Run with args: []
|
||||||
|
Inside rootCmd PostRun with args: []
|
||||||
|
Inside rootCmd PersistentPostRun with args: []
|
||||||
|
|
||||||
|
Inside rootCmd PersistentPreRun with args: [arg1 arg2]
|
||||||
|
Inside subCmd PreRun with args: [arg1 arg2]
|
||||||
|
Inside subCmd Run with args: [arg1 arg2]
|
||||||
|
Inside subCmd PostRun with args: [arg1 arg2]
|
||||||
|
Inside subCmd PersistentPostRun with args: [arg1 arg2]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Suggestions when "unknown command" happens
|
||||||
|
|
||||||
|
Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ hugo srever
|
||||||
|
Error: unknown command "srever" for "hugo"
|
||||||
|
|
||||||
|
Did you mean this?
|
||||||
|
server
|
||||||
|
|
||||||
|
Run 'hugo --help' for usage.
|
||||||
|
```
|
||||||
|
|
||||||
|
Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion.
|
||||||
|
|
||||||
|
If you need to disable suggestions or tweak the string distance in your command, use:
|
||||||
|
|
||||||
|
```go
|
||||||
|
command.DisableSuggestions = true
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```go
|
||||||
|
command.SuggestionsMinimumDistance = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ kubectl remove
|
||||||
|
Error: unknown command "remove" for "kubectl"
|
||||||
|
|
||||||
|
Did you mean this?
|
||||||
|
delete
|
||||||
|
|
||||||
|
Run 'kubectl help' for usage.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generating documentation for your command
|
||||||
|
|
||||||
|
Cobra can generate documentation based on subcommands, flags, etc. Read more about it in the [docs generation documentation](doc/README.md).
|
||||||
|
|
||||||
|
## Generating shell completions
|
||||||
|
|
||||||
|
Cobra can generate a shell-completion file for the following shells: bash, zsh, fish, PowerShell. If you add more information to your commands, these completions can be amazingly powerful and flexible. Read more about it in [Shell Completions](shell_completions.md).
|
||||||
|
|
@ -95,7 +95,7 @@ _%[1]s()
|
||||||
local shellCompDirectiveFilterFileExt=%[6]d
|
local shellCompDirectiveFilterFileExt=%[6]d
|
||||||
local shellCompDirectiveFilterDirs=%[7]d
|
local shellCompDirectiveFilterDirs=%[7]d
|
||||||
|
|
||||||
local lastParam lastChar flagPrefix requestComp out directive compCount comp lastComp
|
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
|
||||||
local -a completions
|
local -a completions
|
||||||
|
|
||||||
__%[1]s_debug "\n========= starting completion logic =========="
|
__%[1]s_debug "\n========= starting completion logic =========="
|
||||||
|
|
@ -163,7 +163,6 @@ _%[1]s()
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
compCount=0
|
|
||||||
while IFS='\n' read -r comp; do
|
while IFS='\n' read -r comp; do
|
||||||
if [ -n "$comp" ]; then
|
if [ -n "$comp" ]; then
|
||||||
# If requested, completions are returned with a description.
|
# If requested, completions are returned with a description.
|
||||||
|
|
@ -175,13 +174,17 @@ _%[1]s()
|
||||||
local tab=$(printf '\t')
|
local tab=$(printf '\t')
|
||||||
comp=${comp//$tab/:}
|
comp=${comp//$tab/:}
|
||||||
|
|
||||||
((compCount++))
|
|
||||||
__%[1]s_debug "Adding completion: ${comp}"
|
__%[1]s_debug "Adding completion: ${comp}"
|
||||||
completions+=${comp}
|
completions+=${comp}
|
||||||
lastComp=$comp
|
lastComp=$comp
|
||||||
fi
|
fi
|
||||||
done < <(printf "%%s\n" "${out[@]}")
|
done < <(printf "%%s\n" "${out[@]}")
|
||||||
|
|
||||||
|
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
|
||||||
|
__%[1]s_debug "Activating nospace."
|
||||||
|
noSpace="-S ''"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
|
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
|
||||||
# File extension filtering
|
# File extension filtering
|
||||||
local filteringCmd
|
local filteringCmd
|
||||||
|
|
@ -208,25 +211,40 @@ _%[1]s()
|
||||||
__%[1]s_debug "Listing directories in ."
|
__%[1]s_debug "Listing directories in ."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local result
|
||||||
_arguments '*:dirname:_files -/'" ${flagPrefix}"
|
_arguments '*:dirname:_files -/'" ${flagPrefix}"
|
||||||
|
result=$?
|
||||||
if [ -n "$subdir" ]; then
|
if [ -n "$subdir" ]; then
|
||||||
popd >/dev/null 2>&1
|
popd >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
elif [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ] && [ ${compCount} -eq 1 ]; then
|
return $result
|
||||||
__%[1]s_debug "Activating nospace."
|
else
|
||||||
# We can use compadd here as there is no description when
|
__%[1]s_debug "Calling _describe"
|
||||||
# there is only one completion.
|
if eval _describe "completions" completions $flagPrefix $noSpace; then
|
||||||
compadd -S '' "${lastComp}"
|
__%[1]s_debug "_describe found some completions"
|
||||||
elif [ ${compCount} -eq 0 ]; then
|
|
||||||
|
# Return the success of having called _describe
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
__%[1]s_debug "_describe did not find completions."
|
||||||
|
__%[1]s_debug "Checking if we should do file completion."
|
||||||
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
|
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
|
||||||
__%[1]s_debug "deactivating file completion"
|
__%[1]s_debug "deactivating file completion"
|
||||||
|
|
||||||
|
# We must return an error code here to let zsh know that there were no
|
||||||
|
# completions found by _describe; this is what will trigger other
|
||||||
|
# matching algorithms to attempt to find completions.
|
||||||
|
# For example zsh can match letters in the middle of words.
|
||||||
|
return 1
|
||||||
else
|
else
|
||||||
# Perform file completion
|
# Perform file completion
|
||||||
__%[1]s_debug "activating file completion"
|
__%[1]s_debug "Activating file completion"
|
||||||
|
|
||||||
|
# We must return the result of this command, so it must be the
|
||||||
|
# last command, or else we must store its result to return it.
|
||||||
_arguments '*:filename:_files'" ${flagPrefix}"
|
_arguments '*:filename:_files'" ${flagPrefix}"
|
||||||
fi
|
fi
|
||||||
else
|
fi
|
||||||
_describe "completions" completions $(echo $flagPrefix)
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
go_import_path: go.opencensus.io
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.11.x
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
GO111MODULE=on
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- make install-tools
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make travis-ci
|
|
||||||
- go run internal/check/version.go # TODO move this to makefile
|
|
||||||
|
|
@ -8,7 +8,7 @@ ALL_PKGS := $(shell go list $(sort $(dir $(ALL_SRC))))
|
||||||
GOTEST_OPT?=-v -race -timeout 30s
|
GOTEST_OPT?=-v -race -timeout 30s
|
||||||
GOTEST_OPT_WITH_COVERAGE = $(GOTEST_OPT) -coverprofile=coverage.txt -covermode=atomic
|
GOTEST_OPT_WITH_COVERAGE = $(GOTEST_OPT) -coverprofile=coverage.txt -covermode=atomic
|
||||||
GOTEST=go test
|
GOTEST=go test
|
||||||
GOFMT=gofmt
|
GOIMPORTS=goimports
|
||||||
GOLINT=golint
|
GOLINT=golint
|
||||||
GOVET=go vet
|
GOVET=go vet
|
||||||
EMBEDMD=embedmd
|
EMBEDMD=embedmd
|
||||||
|
|
@ -17,14 +17,14 @@ TRACE_ID_LINT_EXCEPTION="type name will be used as trace.TraceID by other packag
|
||||||
TRACE_OPTION_LINT_EXCEPTION="type name will be used as trace.TraceOptions by other packages"
|
TRACE_OPTION_LINT_EXCEPTION="type name will be used as trace.TraceOptions by other packages"
|
||||||
README_FILES := $(shell find . -name '*README.md' | sort | tr '\n' ' ')
|
README_FILES := $(shell find . -name '*README.md' | sort | tr '\n' ' ')
|
||||||
|
|
||||||
.DEFAULT_GOAL := fmt-lint-vet-embedmd-test
|
.DEFAULT_GOAL := imports-lint-vet-embedmd-test
|
||||||
|
|
||||||
.PHONY: fmt-lint-vet-embedmd-test
|
.PHONY: imports-lint-vet-embedmd-test
|
||||||
fmt-lint-vet-embedmd-test: fmt lint vet embedmd test
|
imports-lint-vet-embedmd-test: imports lint vet embedmd test
|
||||||
|
|
||||||
# TODO enable test-with-coverage in tavis
|
# TODO enable test-with-coverage in tavis
|
||||||
.PHONY: travis-ci
|
.PHONY: travis-ci
|
||||||
travis-ci: fmt lint vet embedmd test test-386
|
travis-ci: imports lint vet embedmd test test-386
|
||||||
|
|
||||||
all-pkgs:
|
all-pkgs:
|
||||||
@echo $(ALL_PKGS) | tr ' ' '\n' | sort
|
@echo $(ALL_PKGS) | tr ' ' '\n' | sort
|
||||||
|
|
@ -44,15 +44,15 @@ test-386:
|
||||||
test-with-coverage:
|
test-with-coverage:
|
||||||
$(GOTEST) $(GOTEST_OPT_WITH_COVERAGE) $(ALL_PKGS)
|
$(GOTEST) $(GOTEST_OPT_WITH_COVERAGE) $(ALL_PKGS)
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: imports
|
||||||
fmt:
|
imports:
|
||||||
@FMTOUT=`$(GOFMT) -s -l $(ALL_SRC) 2>&1`; \
|
@IMPORTSOUT=`$(GOIMPORTS) -l $(ALL_SRC) 2>&1`; \
|
||||||
if [ "$$FMTOUT" ]; then \
|
if [ "$$IMPORTSOUT" ]; then \
|
||||||
echo "$(GOFMT) FAILED => gofmt the following files:\n"; \
|
echo "$(GOIMPORTS) FAILED => goimports the following files:\n"; \
|
||||||
echo "$$FMTOUT\n"; \
|
echo "$$IMPORTSOUT\n"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
else \
|
else \
|
||||||
echo "Fmt finished successfully"; \
|
echo "Imports finished successfully"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
|
|
@ -91,6 +91,7 @@ embedmd:
|
||||||
|
|
||||||
.PHONY: install-tools
|
.PHONY: install-tools
|
||||||
install-tools:
|
install-tools:
|
||||||
go get -u golang.org/x/tools/cmd/cover
|
|
||||||
go get -u golang.org/x/lint/golint
|
go get -u golang.org/x/lint/golint
|
||||||
|
go get -u golang.org/x/tools/cmd/cover
|
||||||
|
go get -u golang.org/x/tools/cmd/goimports
|
||||||
go get -u github.com/rakyll/embedmd
|
go get -u github.com/rakyll/embedmd
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
module go.opencensus.io
|
module go.opencensus.io
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
|
||||||
github.com/golang/protobuf v1.3.1
|
github.com/golang/protobuf v1.4.3
|
||||||
github.com/google/go-cmp v0.3.0
|
github.com/google/go-cmp v0.5.3
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.6.1
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd // indirect
|
google.golang.org/grpc v1.33.2
|
||||||
golang.org/x/text v0.3.2 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb // indirect
|
|
||||||
google.golang.org/grpc v1.20.1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,47 @@
|
||||||
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=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
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/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
|
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
|
||||||
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
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/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
|
@ -30,24 +52,25 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
|
||||||
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
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/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||||
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=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd h1:r7DufRZuZbWB7j439YfAzP8RPDa9unLkpwQKUYbIMPI=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
@ -55,20 +78,39 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/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/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
||||||
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
||||||
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.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
|
||||||
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||||
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
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/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,16 @@ type Attribute struct {
|
||||||
value interface{}
|
value interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Key returns the attribute's key
|
||||||
|
func (a *Attribute) Key() string {
|
||||||
|
return a.key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the attribute's value
|
||||||
|
func (a *Attribute) Value() interface{} {
|
||||||
|
return a.value
|
||||||
|
}
|
||||||
|
|
||||||
// BoolAttribute returns a bool-valued attribute.
|
// BoolAttribute returns a bool-valued attribute.
|
||||||
func BoolAttribute(key string, value bool) Attribute {
|
func BoolAttribute(key string, value bool) Attribute {
|
||||||
return Attribute{key: key, value: value}
|
return Attribute{key: key, value: value}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ func (lm lruMap) len() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm lruMap) keys() []interface{} {
|
func (lm lruMap) keys() []interface{} {
|
||||||
keys := []interface{}{}
|
keys := make([]interface{}, len(lm.cacheKeys))
|
||||||
for k := range lm.cacheKeys {
|
for k := range lm.cacheKeys {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,10 @@ func (i internalOnly) ReportActiveSpans(name string) []*SpanData {
|
||||||
var out []*SpanData
|
var out []*SpanData
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
for span := range s.active {
|
for activeSpan := range s.active {
|
||||||
out = append(out, span.makeSpanData())
|
if s, ok := activeSpan.(*span); ok {
|
||||||
|
out = append(out, s.makeSpanData())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +187,7 @@ func (i internalOnly) ReportSpansByLatency(name string, minLatency, maxLatency t
|
||||||
// bucketed by latency.
|
// bucketed by latency.
|
||||||
type spanStore struct {
|
type spanStore struct {
|
||||||
mu sync.Mutex // protects everything below.
|
mu sync.Mutex // protects everything below.
|
||||||
active map[*Span]struct{}
|
active map[SpanInterface]struct{}
|
||||||
errors map[int32]*bucket
|
errors map[int32]*bucket
|
||||||
latency []bucket
|
latency []bucket
|
||||||
maxSpansPerErrorBucket int
|
maxSpansPerErrorBucket int
|
||||||
|
|
@ -194,7 +196,7 @@ type spanStore struct {
|
||||||
// newSpanStore creates a span store.
|
// newSpanStore creates a span store.
|
||||||
func newSpanStore(name string, latencyBucketSize int, errorBucketSize int) *spanStore {
|
func newSpanStore(name string, latencyBucketSize int, errorBucketSize int) *spanStore {
|
||||||
s := &spanStore{
|
s := &spanStore{
|
||||||
active: make(map[*Span]struct{}),
|
active: make(map[SpanInterface]struct{}),
|
||||||
latency: make([]bucket, len(defaultLatencies)+1),
|
latency: make([]bucket, len(defaultLatencies)+1),
|
||||||
maxSpansPerErrorBucket: errorBucketSize,
|
maxSpansPerErrorBucket: errorBucketSize,
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +273,7 @@ func (s *spanStore) resize(latencyBucketSize int, errorBucketSize int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add adds a span to the active bucket of the spanStore.
|
// add adds a span to the active bucket of the spanStore.
|
||||||
func (s *spanStore) add(span *Span) {
|
func (s *spanStore) add(span SpanInterface) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
s.active[span] = struct{}{}
|
s.active[span] = struct{}{}
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
|
@ -279,7 +281,7 @@ func (s *spanStore) add(span *Span) {
|
||||||
|
|
||||||
// finished removes a span from the active set, and adds a corresponding
|
// finished removes a span from the active set, and adds a corresponding
|
||||||
// SpanData to a latency or error bucket.
|
// SpanData to a latency or error bucket.
|
||||||
func (s *spanStore) finished(span *Span, sd *SpanData) {
|
func (s *spanStore) finished(span SpanInterface, sd *SpanData) {
|
||||||
latency := sd.EndTime.Sub(sd.StartTime)
|
latency := sd.EndTime.Sub(sd.StartTime)
|
||||||
if latency < 0 {
|
if latency < 0 {
|
||||||
latency = 0
|
latency = 0
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,16 @@ import (
|
||||||
"go.opencensus.io/trace/tracestate"
|
"go.opencensus.io/trace/tracestate"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type tracer struct{}
|
||||||
|
|
||||||
|
var _ Tracer = &tracer{}
|
||||||
|
|
||||||
// Span represents a span of a trace. It has an associated SpanContext, and
|
// Span represents a span of a trace. It has an associated SpanContext, and
|
||||||
// stores data accumulated while the span is active.
|
// stores data accumulated while the span is active.
|
||||||
//
|
//
|
||||||
// Ideally users should interact with Spans by calling the functions in this
|
// Ideally users should interact with Spans by calling the functions in this
|
||||||
// package that take a Context parameter.
|
// package that take a Context parameter.
|
||||||
type Span struct {
|
type span struct {
|
||||||
// data contains information recorded about the span.
|
// data contains information recorded about the span.
|
||||||
//
|
//
|
||||||
// It will be non-nil if we are exporting the span or recording events for it.
|
// It will be non-nil if we are exporting the span or recording events for it.
|
||||||
|
|
@ -66,7 +70,7 @@ type Span struct {
|
||||||
// IsRecordingEvents returns true if events are being recorded for this span.
|
// IsRecordingEvents returns true if events are being recorded for this span.
|
||||||
// Use this check to avoid computing expensive annotations when they will never
|
// Use this check to avoid computing expensive annotations when they will never
|
||||||
// be used.
|
// be used.
|
||||||
func (s *Span) IsRecordingEvents() bool {
|
func (s *span) IsRecordingEvents() bool {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -109,13 +113,13 @@ type SpanContext struct {
|
||||||
type contextKey struct{}
|
type contextKey struct{}
|
||||||
|
|
||||||
// FromContext returns the Span stored in a context, or nil if there isn't one.
|
// FromContext returns the Span stored in a context, or nil if there isn't one.
|
||||||
func FromContext(ctx context.Context) *Span {
|
func (t *tracer) FromContext(ctx context.Context) *Span {
|
||||||
s, _ := ctx.Value(contextKey{}).(*Span)
|
s, _ := ctx.Value(contextKey{}).(*Span)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext returns a new context with the given Span attached.
|
// NewContext returns a new context with the given Span attached.
|
||||||
func NewContext(parent context.Context, s *Span) context.Context {
|
func (t *tracer) NewContext(parent context.Context, s *Span) context.Context {
|
||||||
return context.WithValue(parent, contextKey{}, s)
|
return context.WithValue(parent, contextKey{}, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,12 +170,14 @@ func WithSampler(sampler Sampler) StartOption {
|
||||||
//
|
//
|
||||||
// Returned context contains the newly created span. You can use it to
|
// Returned context contains the newly created span. You can use it to
|
||||||
// propagate the returned span in process.
|
// propagate the returned span in process.
|
||||||
func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
|
func (t *tracer) StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
|
||||||
var opts StartOptions
|
var opts StartOptions
|
||||||
var parent SpanContext
|
var parent SpanContext
|
||||||
if p := FromContext(ctx); p != nil {
|
if p := t.FromContext(ctx); p != nil {
|
||||||
p.addChild()
|
if ps, ok := p.internal.(*span); ok {
|
||||||
parent = p.spanContext
|
ps.addChild()
|
||||||
|
}
|
||||||
|
parent = p.SpanContext()
|
||||||
}
|
}
|
||||||
for _, op := range o {
|
for _, op := range o {
|
||||||
op(&opts)
|
op(&opts)
|
||||||
|
|
@ -180,7 +186,8 @@ func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Cont
|
||||||
|
|
||||||
ctx, end := startExecutionTracerTask(ctx, name)
|
ctx, end := startExecutionTracerTask(ctx, name)
|
||||||
span.executionTracerTaskEnd = end
|
span.executionTracerTaskEnd = end
|
||||||
return NewContext(ctx, span), span
|
extSpan := NewSpan(span)
|
||||||
|
return t.NewContext(ctx, extSpan), extSpan
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartSpanWithRemoteParent starts a new child span of the span from the given parent.
|
// StartSpanWithRemoteParent starts a new child span of the span from the given parent.
|
||||||
|
|
@ -190,7 +197,7 @@ func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Cont
|
||||||
//
|
//
|
||||||
// Returned context contains the newly created span. You can use it to
|
// Returned context contains the newly created span. You can use it to
|
||||||
// propagate the returned span in process.
|
// propagate the returned span in process.
|
||||||
func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) {
|
func (t *tracer) StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) {
|
||||||
var opts StartOptions
|
var opts StartOptions
|
||||||
for _, op := range o {
|
for _, op := range o {
|
||||||
op(&opts)
|
op(&opts)
|
||||||
|
|
@ -198,19 +205,24 @@ func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanCont
|
||||||
span := startSpanInternal(name, parent != SpanContext{}, parent, true, opts)
|
span := startSpanInternal(name, parent != SpanContext{}, parent, true, opts)
|
||||||
ctx, end := startExecutionTracerTask(ctx, name)
|
ctx, end := startExecutionTracerTask(ctx, name)
|
||||||
span.executionTracerTaskEnd = end
|
span.executionTracerTaskEnd = end
|
||||||
return NewContext(ctx, span), span
|
extSpan := NewSpan(span)
|
||||||
|
return t.NewContext(ctx, extSpan), extSpan
|
||||||
}
|
}
|
||||||
|
|
||||||
func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *Span {
|
func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *span {
|
||||||
span := &Span{}
|
s := &span{}
|
||||||
span.spanContext = parent
|
s.spanContext = parent
|
||||||
|
|
||||||
cfg := config.Load().(*Config)
|
cfg := config.Load().(*Config)
|
||||||
|
if gen, ok := cfg.IDGenerator.(*defaultIDGenerator); ok {
|
||||||
|
// lazy initialization
|
||||||
|
gen.init()
|
||||||
|
}
|
||||||
|
|
||||||
if !hasParent {
|
if !hasParent {
|
||||||
span.spanContext.TraceID = cfg.IDGenerator.NewTraceID()
|
s.spanContext.TraceID = cfg.IDGenerator.NewTraceID()
|
||||||
}
|
}
|
||||||
span.spanContext.SpanID = cfg.IDGenerator.NewSpanID()
|
s.spanContext.SpanID = cfg.IDGenerator.NewSpanID()
|
||||||
sampler := cfg.DefaultSampler
|
sampler := cfg.DefaultSampler
|
||||||
|
|
||||||
if !hasParent || remoteParent || o.Sampler != nil {
|
if !hasParent || remoteParent || o.Sampler != nil {
|
||||||
|
|
@ -222,47 +234,47 @@ func startSpanInternal(name string, hasParent bool, parent SpanContext, remotePa
|
||||||
if o.Sampler != nil {
|
if o.Sampler != nil {
|
||||||
sampler = o.Sampler
|
sampler = o.Sampler
|
||||||
}
|
}
|
||||||
span.spanContext.setIsSampled(sampler(SamplingParameters{
|
s.spanContext.setIsSampled(sampler(SamplingParameters{
|
||||||
ParentContext: parent,
|
ParentContext: parent,
|
||||||
TraceID: span.spanContext.TraceID,
|
TraceID: s.spanContext.TraceID,
|
||||||
SpanID: span.spanContext.SpanID,
|
SpanID: s.spanContext.SpanID,
|
||||||
Name: name,
|
Name: name,
|
||||||
HasRemoteParent: remoteParent}).Sample)
|
HasRemoteParent: remoteParent}).Sample)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !internal.LocalSpanStoreEnabled && !span.spanContext.IsSampled() {
|
if !internal.LocalSpanStoreEnabled && !s.spanContext.IsSampled() {
|
||||||
return span
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
span.data = &SpanData{
|
s.data = &SpanData{
|
||||||
SpanContext: span.spanContext,
|
SpanContext: s.spanContext,
|
||||||
StartTime: time.Now(),
|
StartTime: time.Now(),
|
||||||
SpanKind: o.SpanKind,
|
SpanKind: o.SpanKind,
|
||||||
Name: name,
|
Name: name,
|
||||||
HasRemoteParent: remoteParent,
|
HasRemoteParent: remoteParent,
|
||||||
}
|
}
|
||||||
span.lruAttributes = newLruMap(cfg.MaxAttributesPerSpan)
|
s.lruAttributes = newLruMap(cfg.MaxAttributesPerSpan)
|
||||||
span.annotations = newEvictedQueue(cfg.MaxAnnotationEventsPerSpan)
|
s.annotations = newEvictedQueue(cfg.MaxAnnotationEventsPerSpan)
|
||||||
span.messageEvents = newEvictedQueue(cfg.MaxMessageEventsPerSpan)
|
s.messageEvents = newEvictedQueue(cfg.MaxMessageEventsPerSpan)
|
||||||
span.links = newEvictedQueue(cfg.MaxLinksPerSpan)
|
s.links = newEvictedQueue(cfg.MaxLinksPerSpan)
|
||||||
|
|
||||||
if hasParent {
|
if hasParent {
|
||||||
span.data.ParentSpanID = parent.SpanID
|
s.data.ParentSpanID = parent.SpanID
|
||||||
}
|
}
|
||||||
if internal.LocalSpanStoreEnabled {
|
if internal.LocalSpanStoreEnabled {
|
||||||
var ss *spanStore
|
var ss *spanStore
|
||||||
ss = spanStoreForNameCreateIfNew(name)
|
ss = spanStoreForNameCreateIfNew(name)
|
||||||
if ss != nil {
|
if ss != nil {
|
||||||
span.spanStore = ss
|
s.spanStore = ss
|
||||||
ss.add(span)
|
ss.add(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return span
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// End ends the span.
|
// End ends the span.
|
||||||
func (s *Span) End() {
|
func (s *span) End() {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -292,7 +304,7 @@ func (s *Span) End() {
|
||||||
|
|
||||||
// makeSpanData produces a SpanData representing the current state of the Span.
|
// makeSpanData produces a SpanData representing the current state of the Span.
|
||||||
// It requires that s.data is non-nil.
|
// It requires that s.data is non-nil.
|
||||||
func (s *Span) makeSpanData() *SpanData {
|
func (s *span) makeSpanData() *SpanData {
|
||||||
var sd SpanData
|
var sd SpanData
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
sd = *s.data
|
sd = *s.data
|
||||||
|
|
@ -317,7 +329,7 @@ func (s *Span) makeSpanData() *SpanData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SpanContext returns the SpanContext of the span.
|
// SpanContext returns the SpanContext of the span.
|
||||||
func (s *Span) SpanContext() SpanContext {
|
func (s *span) SpanContext() SpanContext {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return SpanContext{}
|
return SpanContext{}
|
||||||
}
|
}
|
||||||
|
|
@ -325,7 +337,7 @@ func (s *Span) SpanContext() SpanContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetName sets the name of the span, if it is recording events.
|
// SetName sets the name of the span, if it is recording events.
|
||||||
func (s *Span) SetName(name string) {
|
func (s *span) SetName(name string) {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -335,7 +347,7 @@ func (s *Span) SetName(name string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStatus sets the status of the span, if it is recording events.
|
// SetStatus sets the status of the span, if it is recording events.
|
||||||
func (s *Span) SetStatus(status Status) {
|
func (s *span) SetStatus(status Status) {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -344,32 +356,32 @@ func (s *Span) SetStatus(status Status) {
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Span) interfaceArrayToLinksArray() []Link {
|
func (s *span) interfaceArrayToLinksArray() []Link {
|
||||||
linksArr := make([]Link, 0)
|
linksArr := make([]Link, 0, len(s.links.queue))
|
||||||
for _, value := range s.links.queue {
|
for _, value := range s.links.queue {
|
||||||
linksArr = append(linksArr, value.(Link))
|
linksArr = append(linksArr, value.(Link))
|
||||||
}
|
}
|
||||||
return linksArr
|
return linksArr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Span) interfaceArrayToMessageEventArray() []MessageEvent {
|
func (s *span) interfaceArrayToMessageEventArray() []MessageEvent {
|
||||||
messageEventArr := make([]MessageEvent, 0)
|
messageEventArr := make([]MessageEvent, 0, len(s.messageEvents.queue))
|
||||||
for _, value := range s.messageEvents.queue {
|
for _, value := range s.messageEvents.queue {
|
||||||
messageEventArr = append(messageEventArr, value.(MessageEvent))
|
messageEventArr = append(messageEventArr, value.(MessageEvent))
|
||||||
}
|
}
|
||||||
return messageEventArr
|
return messageEventArr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Span) interfaceArrayToAnnotationArray() []Annotation {
|
func (s *span) interfaceArrayToAnnotationArray() []Annotation {
|
||||||
annotationArr := make([]Annotation, 0)
|
annotationArr := make([]Annotation, 0, len(s.annotations.queue))
|
||||||
for _, value := range s.annotations.queue {
|
for _, value := range s.annotations.queue {
|
||||||
annotationArr = append(annotationArr, value.(Annotation))
|
annotationArr = append(annotationArr, value.(Annotation))
|
||||||
}
|
}
|
||||||
return annotationArr
|
return annotationArr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Span) lruAttributesToAttributeMap() map[string]interface{} {
|
func (s *span) lruAttributesToAttributeMap() map[string]interface{} {
|
||||||
attributes := make(map[string]interface{})
|
attributes := make(map[string]interface{}, s.lruAttributes.len())
|
||||||
for _, key := range s.lruAttributes.keys() {
|
for _, key := range s.lruAttributes.keys() {
|
||||||
value, ok := s.lruAttributes.get(key)
|
value, ok := s.lruAttributes.get(key)
|
||||||
if ok {
|
if ok {
|
||||||
|
|
@ -380,13 +392,13 @@ func (s *Span) lruAttributesToAttributeMap() map[string]interface{} {
|
||||||
return attributes
|
return attributes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Span) copyToCappedAttributes(attributes []Attribute) {
|
func (s *span) copyToCappedAttributes(attributes []Attribute) {
|
||||||
for _, a := range attributes {
|
for _, a := range attributes {
|
||||||
s.lruAttributes.add(a.key, a.value)
|
s.lruAttributes.add(a.key, a.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Span) addChild() {
|
func (s *span) addChild() {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -398,7 +410,7 @@ func (s *Span) addChild() {
|
||||||
// AddAttributes sets attributes in the span.
|
// AddAttributes sets attributes in the span.
|
||||||
//
|
//
|
||||||
// Existing attributes whose keys appear in the attributes parameter are overwritten.
|
// Existing attributes whose keys appear in the attributes parameter are overwritten.
|
||||||
func (s *Span) AddAttributes(attributes ...Attribute) {
|
func (s *span) AddAttributes(attributes ...Attribute) {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -407,49 +419,27 @@ func (s *Span) AddAttributes(attributes ...Attribute) {
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyAttributes copies a slice of Attributes into a map.
|
func (s *span) printStringInternal(attributes []Attribute, str string) {
|
||||||
func copyAttributes(m map[string]interface{}, attributes []Attribute) {
|
|
||||||
for _, a := range attributes {
|
|
||||||
m[a.key] = a.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Span) lazyPrintfInternal(attributes []Attribute, format string, a ...interface{}) {
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
msg := fmt.Sprintf(format, a...)
|
var am map[string]interface{}
|
||||||
var m map[string]interface{}
|
|
||||||
s.mu.Lock()
|
|
||||||
if len(attributes) != 0 {
|
if len(attributes) != 0 {
|
||||||
m = make(map[string]interface{})
|
am = make(map[string]interface{}, len(attributes))
|
||||||
copyAttributes(m, attributes)
|
for _, attr := range attributes {
|
||||||
|
am[attr.key] = attr.value
|
||||||
}
|
}
|
||||||
s.annotations.add(Annotation{
|
|
||||||
Time: now,
|
|
||||||
Message: msg,
|
|
||||||
Attributes: m,
|
|
||||||
})
|
|
||||||
s.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Span) printStringInternal(attributes []Attribute, str string) {
|
|
||||||
now := time.Now()
|
|
||||||
var a map[string]interface{}
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
if len(attributes) != 0 {
|
|
||||||
a = make(map[string]interface{})
|
|
||||||
copyAttributes(a, attributes)
|
|
||||||
}
|
|
||||||
s.annotations.add(Annotation{
|
s.annotations.add(Annotation{
|
||||||
Time: now,
|
Time: now,
|
||||||
Message: str,
|
Message: str,
|
||||||
Attributes: a,
|
Attributes: am,
|
||||||
})
|
})
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Annotate adds an annotation with attributes.
|
// Annotate adds an annotation with attributes.
|
||||||
// Attributes can be nil.
|
// Attributes can be nil.
|
||||||
func (s *Span) Annotate(attributes []Attribute, str string) {
|
func (s *span) Annotate(attributes []Attribute, str string) {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -457,11 +447,11 @@ func (s *Span) Annotate(attributes []Attribute, str string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Annotatef adds an annotation with attributes.
|
// Annotatef adds an annotation with attributes.
|
||||||
func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}) {
|
func (s *span) Annotatef(attributes []Attribute, format string, a ...interface{}) {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.lazyPrintfInternal(attributes, format, a...)
|
s.printStringInternal(attributes, fmt.Sprintf(format, a...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddMessageSendEvent adds a message send event to the span.
|
// AddMessageSendEvent adds a message send event to the span.
|
||||||
|
|
@ -470,7 +460,7 @@ func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}
|
||||||
// unique in this span and the same between the send event and the receive
|
// unique in this span and the same between the send event and the receive
|
||||||
// event (this allows to identify a message between the sender and receiver).
|
// event (this allows to identify a message between the sender and receiver).
|
||||||
// For example, this could be a sequence id.
|
// For example, this could be a sequence id.
|
||||||
func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
func (s *span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -492,7 +482,7 @@ func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedBy
|
||||||
// unique in this span and the same between the send event and the receive
|
// unique in this span and the same between the send event and the receive
|
||||||
// event (this allows to identify a message between the sender and receiver).
|
// event (this allows to identify a message between the sender and receiver).
|
||||||
// For example, this could be a sequence id.
|
// For example, this could be a sequence id.
|
||||||
func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
func (s *span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -509,7 +499,7 @@ func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compresse
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddLink adds a link to the span.
|
// AddLink adds a link to the span.
|
||||||
func (s *Span) AddLink(l Link) {
|
func (s *span) AddLink(l Link) {
|
||||||
if !s.IsRecordingEvents() {
|
if !s.IsRecordingEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -518,7 +508,7 @@ func (s *Span) AddLink(l Link) {
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Span) String() string {
|
func (s *span) String() string {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return "<nil>"
|
return "<nil>"
|
||||||
}
|
}
|
||||||
|
|
@ -534,20 +524,9 @@ func (s *Span) String() string {
|
||||||
var config atomic.Value // access atomically
|
var config atomic.Value // access atomically
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gen := &defaultIDGenerator{}
|
|
||||||
// initialize traceID and spanID generators.
|
|
||||||
var rngSeed int64
|
|
||||||
for _, p := range []interface{}{
|
|
||||||
&rngSeed, &gen.traceIDAdd, &gen.nextSpanID, &gen.spanIDInc,
|
|
||||||
} {
|
|
||||||
binary.Read(crand.Reader, binary.LittleEndian, p)
|
|
||||||
}
|
|
||||||
gen.traceIDRand = rand.New(rand.NewSource(rngSeed))
|
|
||||||
gen.spanIDInc |= 1
|
|
||||||
|
|
||||||
config.Store(&Config{
|
config.Store(&Config{
|
||||||
DefaultSampler: ProbabilitySampler(defaultSamplingProbability),
|
DefaultSampler: ProbabilitySampler(defaultSamplingProbability),
|
||||||
IDGenerator: gen,
|
IDGenerator: &defaultIDGenerator{},
|
||||||
MaxAttributesPerSpan: DefaultMaxAttributesPerSpan,
|
MaxAttributesPerSpan: DefaultMaxAttributesPerSpan,
|
||||||
MaxAnnotationEventsPerSpan: DefaultMaxAnnotationEventsPerSpan,
|
MaxAnnotationEventsPerSpan: DefaultMaxAnnotationEventsPerSpan,
|
||||||
MaxMessageEventsPerSpan: DefaultMaxMessageEventsPerSpan,
|
MaxMessageEventsPerSpan: DefaultMaxMessageEventsPerSpan,
|
||||||
|
|
@ -571,6 +550,24 @@ type defaultIDGenerator struct {
|
||||||
|
|
||||||
traceIDAdd [2]uint64
|
traceIDAdd [2]uint64
|
||||||
traceIDRand *rand.Rand
|
traceIDRand *rand.Rand
|
||||||
|
|
||||||
|
initOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
// init initializes the generator on the first call to avoid consuming entropy
|
||||||
|
// unnecessarily.
|
||||||
|
func (gen *defaultIDGenerator) init() {
|
||||||
|
gen.initOnce.Do(func() {
|
||||||
|
// initialize traceID and spanID generators.
|
||||||
|
var rngSeed int64
|
||||||
|
for _, p := range []interface{}{
|
||||||
|
&rngSeed, &gen.traceIDAdd, &gen.nextSpanID, &gen.spanIDInc,
|
||||||
|
} {
|
||||||
|
binary.Read(crand.Reader, binary.LittleEndian, p)
|
||||||
|
}
|
||||||
|
gen.traceIDRand = rand.New(rand.NewSource(rngSeed))
|
||||||
|
gen.spanIDInc |= 1
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSpanID returns a non-zero span ID from a randomly-chosen sequence.
|
// NewSpanID returns a non-zero span ID from a randomly-chosen sequence.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,265 @@
|
||||||
|
// Copyright 2020, OpenCensus 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 trace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultTracer is the tracer used when package-level exported functions are invoked.
|
||||||
|
var DefaultTracer Tracer = &tracer{}
|
||||||
|
|
||||||
|
// Tracer can start spans and access context functions.
|
||||||
|
type Tracer interface {
|
||||||
|
|
||||||
|
// StartSpan starts a new child span of the current span in the context. If
|
||||||
|
// there is no span in the context, creates a new trace and span.
|
||||||
|
//
|
||||||
|
// Returned context contains the newly created span. You can use it to
|
||||||
|
// propagate the returned span in process.
|
||||||
|
StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span)
|
||||||
|
|
||||||
|
// StartSpanWithRemoteParent starts a new child span of the span from the given parent.
|
||||||
|
//
|
||||||
|
// If the incoming context contains a parent, it ignores. StartSpanWithRemoteParent is
|
||||||
|
// preferred for cases where the parent is propagated via an incoming request.
|
||||||
|
//
|
||||||
|
// Returned context contains the newly created span. You can use it to
|
||||||
|
// propagate the returned span in process.
|
||||||
|
StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span)
|
||||||
|
|
||||||
|
// FromContext returns the Span stored in a context, or nil if there isn't one.
|
||||||
|
FromContext(ctx context.Context) *Span
|
||||||
|
|
||||||
|
// NewContext returns a new context with the given Span attached.
|
||||||
|
NewContext(parent context.Context, s *Span) context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartSpan starts a new child span of the current span in the context. If
|
||||||
|
// there is no span in the context, creates a new trace and span.
|
||||||
|
//
|
||||||
|
// Returned context contains the newly created span. You can use it to
|
||||||
|
// propagate the returned span in process.
|
||||||
|
func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
|
||||||
|
return DefaultTracer.StartSpan(ctx, name, o...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartSpanWithRemoteParent starts a new child span of the span from the given parent.
|
||||||
|
//
|
||||||
|
// If the incoming context contains a parent, it ignores. StartSpanWithRemoteParent is
|
||||||
|
// preferred for cases where the parent is propagated via an incoming request.
|
||||||
|
//
|
||||||
|
// Returned context contains the newly created span. You can use it to
|
||||||
|
// propagate the returned span in process.
|
||||||
|
func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) {
|
||||||
|
return DefaultTracer.StartSpanWithRemoteParent(ctx, name, parent, o...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext returns the Span stored in a context, or a Span that is not
|
||||||
|
// recording events if there isn't one.
|
||||||
|
func FromContext(ctx context.Context) *Span {
|
||||||
|
return DefaultTracer.FromContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContext returns a new context with the given Span attached.
|
||||||
|
func NewContext(parent context.Context, s *Span) context.Context {
|
||||||
|
return DefaultTracer.NewContext(parent, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpanInterface represents a span of a trace. It has an associated SpanContext, and
|
||||||
|
// stores data accumulated while the span is active.
|
||||||
|
//
|
||||||
|
// Ideally users should interact with Spans by calling the functions in this
|
||||||
|
// package that take a Context parameter.
|
||||||
|
type SpanInterface interface {
|
||||||
|
|
||||||
|
// IsRecordingEvents returns true if events are being recorded for this span.
|
||||||
|
// Use this check to avoid computing expensive annotations when they will never
|
||||||
|
// be used.
|
||||||
|
IsRecordingEvents() bool
|
||||||
|
|
||||||
|
// End ends the span.
|
||||||
|
End()
|
||||||
|
|
||||||
|
// SpanContext returns the SpanContext of the span.
|
||||||
|
SpanContext() SpanContext
|
||||||
|
|
||||||
|
// SetName sets the name of the span, if it is recording events.
|
||||||
|
SetName(name string)
|
||||||
|
|
||||||
|
// SetStatus sets the status of the span, if it is recording events.
|
||||||
|
SetStatus(status Status)
|
||||||
|
|
||||||
|
// AddAttributes sets attributes in the span.
|
||||||
|
//
|
||||||
|
// Existing attributes whose keys appear in the attributes parameter are overwritten.
|
||||||
|
AddAttributes(attributes ...Attribute)
|
||||||
|
|
||||||
|
// Annotate adds an annotation with attributes.
|
||||||
|
// Attributes can be nil.
|
||||||
|
Annotate(attributes []Attribute, str string)
|
||||||
|
|
||||||
|
// Annotatef adds an annotation with attributes.
|
||||||
|
Annotatef(attributes []Attribute, format string, a ...interface{})
|
||||||
|
|
||||||
|
// AddMessageSendEvent adds a message send event to the span.
|
||||||
|
//
|
||||||
|
// messageID is an identifier for the message, which is recommended to be
|
||||||
|
// unique in this span and the same between the send event and the receive
|
||||||
|
// event (this allows to identify a message between the sender and receiver).
|
||||||
|
// For example, this could be a sequence id.
|
||||||
|
AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64)
|
||||||
|
|
||||||
|
// AddMessageReceiveEvent adds a message receive event to the span.
|
||||||
|
//
|
||||||
|
// messageID is an identifier for the message, which is recommended to be
|
||||||
|
// unique in this span and the same between the send event and the receive
|
||||||
|
// event (this allows to identify a message between the sender and receiver).
|
||||||
|
// For example, this could be a sequence id.
|
||||||
|
AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64)
|
||||||
|
|
||||||
|
// AddLink adds a link to the span.
|
||||||
|
AddLink(l Link)
|
||||||
|
|
||||||
|
// String prints a string representation of a span.
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSpan is a convenience function for creating a *Span out of a *span
|
||||||
|
func NewSpan(s SpanInterface) *Span {
|
||||||
|
return &Span{internal: s}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Span is a struct wrapper around the SpanInt interface, which allows correctly handling
|
||||||
|
// nil spans, while also allowing the SpanInterface implementation to be swapped out.
|
||||||
|
type Span struct {
|
||||||
|
internal SpanInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal returns the underlying implementation of the Span
|
||||||
|
func (s *Span) Internal() SpanInterface {
|
||||||
|
return s.internal
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRecordingEvents returns true if events are being recorded for this span.
|
||||||
|
// Use this check to avoid computing expensive annotations when they will never
|
||||||
|
// be used.
|
||||||
|
func (s *Span) IsRecordingEvents() bool {
|
||||||
|
if s == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return s.internal.IsRecordingEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
// End ends the span.
|
||||||
|
func (s *Span) End() {
|
||||||
|
if s == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpanContext returns the SpanContext of the span.
|
||||||
|
func (s *Span) SpanContext() SpanContext {
|
||||||
|
if s == nil {
|
||||||
|
return SpanContext{}
|
||||||
|
}
|
||||||
|
return s.internal.SpanContext()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets the name of the span, if it is recording events.
|
||||||
|
func (s *Span) SetName(name string) {
|
||||||
|
if !s.IsRecordingEvents() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.SetName(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStatus sets the status of the span, if it is recording events.
|
||||||
|
func (s *Span) SetStatus(status Status) {
|
||||||
|
if !s.IsRecordingEvents() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.SetStatus(status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAttributes sets attributes in the span.
|
||||||
|
//
|
||||||
|
// Existing attributes whose keys appear in the attributes parameter are overwritten.
|
||||||
|
func (s *Span) AddAttributes(attributes ...Attribute) {
|
||||||
|
if !s.IsRecordingEvents() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.AddAttributes(attributes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotate adds an annotation with attributes.
|
||||||
|
// Attributes can be nil.
|
||||||
|
func (s *Span) Annotate(attributes []Attribute, str string) {
|
||||||
|
if !s.IsRecordingEvents() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.Annotate(attributes, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotatef adds an annotation with attributes.
|
||||||
|
func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}) {
|
||||||
|
if !s.IsRecordingEvents() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.Annotatef(attributes, format, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMessageSendEvent adds a message send event to the span.
|
||||||
|
//
|
||||||
|
// messageID is an identifier for the message, which is recommended to be
|
||||||
|
// unique in this span and the same between the send event and the receive
|
||||||
|
// event (this allows to identify a message between the sender and receiver).
|
||||||
|
// For example, this could be a sequence id.
|
||||||
|
func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
||||||
|
if !s.IsRecordingEvents() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMessageReceiveEvent adds a message receive event to the span.
|
||||||
|
//
|
||||||
|
// messageID is an identifier for the message, which is recommended to be
|
||||||
|
// unique in this span and the same between the send event and the receive
|
||||||
|
// event (this allows to identify a message between the sender and receiver).
|
||||||
|
// For example, this could be a sequence id.
|
||||||
|
func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
||||||
|
if !s.IsRecordingEvents() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLink adds a link to the span.
|
||||||
|
func (s *Span) AddLink(l Link) {
|
||||||
|
if !s.IsRecordingEvents() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.internal.AddLink(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String prints a string representation of a span.
|
||||||
|
func (s *Span) String() string {
|
||||||
|
if s == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return s.internal.String()
|
||||||
|
}
|
||||||
|
|
@ -35,7 +35,7 @@ install:
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- set -e
|
- set -e
|
||||||
- if [[ -n "${TESTEXTRAS}" ]]; then examples/examples_test.sh; interop/interop_test.sh; make testsubmodule; exit 0; fi
|
- if [[ -n "${TESTEXTRAS}" ]]; then examples/examples_test.sh; security/advancedtls/examples/examples_test.sh; interop/interop_test.sh; make testsubmodule; exit 0; fi
|
||||||
- if [[ -n "${VET}" ]]; then ./vet.sh; fi
|
- if [[ -n "${VET}" ]]; then ./vet.sh; fi
|
||||||
- if [[ -n "${GAE}" ]]; then make testappengine; exit 0; fi
|
- if [[ -n "${GAE}" ]]; then make testappengine; exit 0; fi
|
||||||
- if [[ -n "${RACE}" ]]; then make testrace; exit 0; fi
|
- if [[ -n "${RACE}" ]]; then make testrace; exit 0; fi
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
all: vet test testrace
|
all: vet test testrace
|
||||||
|
|
||||||
build: deps
|
build:
|
||||||
go build google.golang.org/grpc/...
|
go build google.golang.org/grpc/...
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
go clean -i google.golang.org/grpc/...
|
go clean -i google.golang.org/grpc/...
|
||||||
|
|
||||||
deps:
|
deps:
|
||||||
go get -d -v google.golang.org/grpc/...
|
GO111MODULE=on go get -d -v google.golang.org/grpc/...
|
||||||
|
|
||||||
proto:
|
proto:
|
||||||
@ if ! which protoc > /dev/null; then \
|
@ if ! which protoc > /dev/null; then \
|
||||||
|
|
@ -16,30 +16,18 @@ proto:
|
||||||
fi
|
fi
|
||||||
go generate google.golang.org/grpc/...
|
go generate google.golang.org/grpc/...
|
||||||
|
|
||||||
test: testdeps
|
test:
|
||||||
go test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
go test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
||||||
|
|
||||||
testsubmodule: testdeps
|
testsubmodule:
|
||||||
cd security/advancedtls && go test -cpu 1,4 -timeout 7m google.golang.org/grpc/security/advancedtls/...
|
cd security/advancedtls && go test -cpu 1,4 -timeout 7m google.golang.org/grpc/security/advancedtls/...
|
||||||
cd security/authorization && go test -cpu 1,4 -timeout 7m google.golang.org/grpc/security/authorization/...
|
cd security/authorization && go test -cpu 1,4 -timeout 7m google.golang.org/grpc/security/authorization/...
|
||||||
|
|
||||||
testappengine: testappenginedeps
|
testrace:
|
||||||
goapp test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
|
||||||
|
|
||||||
testappenginedeps:
|
|
||||||
goapp get -d -v -t -tags 'appengine appenginevm' google.golang.org/grpc/...
|
|
||||||
|
|
||||||
testdeps:
|
|
||||||
go get -d -v -t google.golang.org/grpc/...
|
|
||||||
|
|
||||||
testrace: testdeps
|
|
||||||
go test -race -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
go test -race -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
||||||
|
|
||||||
updatedeps:
|
testdeps:
|
||||||
go get -d -v -u -f google.golang.org/grpc/...
|
GO111MODULE=on go get -d -v -t google.golang.org/grpc/...
|
||||||
|
|
||||||
updatetestdeps:
|
|
||||||
go get -d -v -t -u -f google.golang.org/grpc/...
|
|
||||||
|
|
||||||
vet: vetdeps
|
vet: vetdeps
|
||||||
./vet.sh
|
./vet.sh
|
||||||
|
|
@ -51,14 +39,10 @@ vetdeps:
|
||||||
all \
|
all \
|
||||||
build \
|
build \
|
||||||
clean \
|
clean \
|
||||||
deps \
|
|
||||||
proto \
|
proto \
|
||||||
test \
|
test \
|
||||||
testappengine \
|
testappengine \
|
||||||
testappenginedeps \
|
testappenginedeps \
|
||||||
testdeps \
|
|
||||||
testrace \
|
testrace \
|
||||||
updatedeps \
|
|
||||||
updatetestdeps \
|
|
||||||
vet \
|
vet \
|
||||||
vetdeps
|
vetdeps
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Security Policy
|
||||||
|
|
||||||
|
For information on gRPC Security Policy and reporting potentional security issues, please see [gRPC CVE Process](https://github.com/grpc/proposal/blob/master/P4-grpc-cve-process.md).
|
||||||
|
|
@ -101,6 +101,9 @@ type SubConn interface {
|
||||||
// a new connection will be created.
|
// a new connection will be created.
|
||||||
//
|
//
|
||||||
// This will trigger a state transition for the SubConn.
|
// This will trigger a state transition for the SubConn.
|
||||||
|
//
|
||||||
|
// Deprecated: This method is now part of the ClientConn interface and will
|
||||||
|
// eventually be removed from here.
|
||||||
UpdateAddresses([]resolver.Address)
|
UpdateAddresses([]resolver.Address)
|
||||||
// Connect starts the connecting for this SubConn.
|
// Connect starts the connecting for this SubConn.
|
||||||
Connect()
|
Connect()
|
||||||
|
|
@ -143,6 +146,13 @@ type ClientConn interface {
|
||||||
// RemoveSubConn removes the SubConn from ClientConn.
|
// RemoveSubConn removes the SubConn from ClientConn.
|
||||||
// The SubConn will be shutdown.
|
// The SubConn will be shutdown.
|
||||||
RemoveSubConn(SubConn)
|
RemoveSubConn(SubConn)
|
||||||
|
// UpdateAddresses updates the addresses used in the passed in SubConn.
|
||||||
|
// gRPC checks if the currently connected address is still in the new list.
|
||||||
|
// If so, the connection will be kept. Else, the connection will be
|
||||||
|
// gracefully closed, and a new connection will be created.
|
||||||
|
//
|
||||||
|
// This will trigger a state transition for the SubConn.
|
||||||
|
UpdateAddresses(SubConn, []resolver.Address)
|
||||||
|
|
||||||
// UpdateState notifies gRPC that the balancer's internal state has
|
// UpdateState notifies gRPC that the balancer's internal state has
|
||||||
// changed.
|
// changed.
|
||||||
|
|
@ -174,6 +184,10 @@ type BuildOptions struct {
|
||||||
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.
|
// ChannelzParentID is the entity parent's channelz unique identification number.
|
||||||
ChannelzParentID int64
|
ChannelzParentID int64
|
||||||
|
// CustomUserAgent is the custom user agent set on the parent ClientConn.
|
||||||
|
// The balancer should set the same custom user agent if it creates a
|
||||||
|
// ClientConn.
|
||||||
|
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 same resolver.Target as
|
||||||
// passed to the resolver.
|
// passed to the resolver.
|
||||||
// See the documentation for the resolver.Target type for details about what it contains.
|
// See the documentation for the resolver.Target type for details about what it contains.
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ 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"
|
||||||
|
|
@ -41,7 +42,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]balancer.SubConn),
|
subConns: make(map[resolver.Address]subConnInfo),
|
||||||
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,
|
||||||
|
|
@ -57,6 +58,11 @@ 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
|
||||||
|
|
@ -64,7 +70,7 @@ type baseBalancer struct {
|
||||||
csEvltr *balancer.ConnectivityStateEvaluator
|
csEvltr *balancer.ConnectivityStateEvaluator
|
||||||
state connectivity.State
|
state connectivity.State
|
||||||
|
|
||||||
subConns map[resolver.Address]balancer.SubConn
|
subConns map[resolver.Address]subConnInfo // `attributes` is stripped from the keys of this map (the addresses)
|
||||||
scStates map[balancer.SubConn]connectivity.State
|
scStates map[balancer.SubConn]connectivity.State
|
||||||
picker balancer.Picker
|
picker balancer.Picker
|
||||||
config Config
|
config Config
|
||||||
|
|
@ -101,23 +107,49 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
|
||||||
// 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 := make(map[resolver.Address]struct{})
|
||||||
for _, a := range s.ResolverState.Addresses {
|
for _, a := range s.ResolverState.Addresses {
|
||||||
addrsSet[a] = struct{}{}
|
// Strip attributes from addresses before using them as map keys. So
|
||||||
if _, ok := b.subConns[a]; !ok {
|
// that when two addresses only differ in attributes pointers (but with
|
||||||
|
// 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[a] = sc
|
b.subConns[aNoAttrs] = subConnInfo{subConn: sc, attrs: a.Attributes}
|
||||||
b.scStates[sc] = connectivity.Idle
|
b.scStates[sc] = 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, sc := range b.subConns {
|
for a, scInfo := range b.subConns {
|
||||||
// a was removed by resolver.
|
// a was removed by resolver.
|
||||||
if _, ok := addrsSet[a]; !ok {
|
if _, ok := addrsSet[a]; !ok {
|
||||||
b.cc.RemoveSubConn(sc)
|
b.cc.RemoveSubConn(scInfo.subConn)
|
||||||
delete(b.subConns, a)
|
delete(b.subConns, 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.
|
||||||
|
|
@ -160,9 +192,10 @@ 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, sc := range b.subConns {
|
for addr, scInfo := range b.subConns {
|
||||||
if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
|
if st, ok := b.scStates[scInfo.subConn]; ok && st == connectivity.Ready {
|
||||||
readySCs[sc] = SubConnInfo{Address: addr}
|
addr.Attributes = scInfo.attrs
|
||||||
|
readySCs[scInfo.subConn] = SubConnInfo{Address: addr}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})
|
b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,14 @@ func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
|
||||||
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
|
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
|
||||||
|
acbw, ok := sc.(*acBalancerWrapper)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
acbw.UpdateAddresses(addrs)
|
||||||
|
}
|
||||||
|
|
||||||
func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
|
func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
|
||||||
ccb.mu.Lock()
|
ccb.mu.Lock()
|
||||||
defer ccb.mu.Unlock()
|
defer ccb.mu.Unlock()
|
||||||
|
|
@ -197,7 +205,7 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
|
||||||
acbw.mu.Lock()
|
acbw.mu.Lock()
|
||||||
defer acbw.mu.Unlock()
|
defer acbw.mu.Unlock()
|
||||||
if len(addrs) <= 0 {
|
if len(addrs) <= 0 {
|
||||||
acbw.ac.tearDown(errConnDrain)
|
acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !acbw.ac.tryUpdateAddrs(addrs) {
|
if !acbw.ac.tryUpdateAddrs(addrs) {
|
||||||
|
|
@ -212,7 +220,7 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
|
||||||
acbw.ac.acbw = nil
|
acbw.ac.acbw = nil
|
||||||
acbw.ac.mu.Unlock()
|
acbw.ac.mu.Unlock()
|
||||||
acState := acbw.ac.getState()
|
acState := acbw.ac.getState()
|
||||||
acbw.ac.tearDown(errConnDrain)
|
acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain)
|
||||||
|
|
||||||
if acState == connectivity.Shutdown {
|
if acState == connectivity.Shutdown {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,17 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.25.0
|
||||||
// protoc v3.3.0
|
// protoc v3.14.0
|
||||||
// source: grpc/binlog/v1/binarylog.proto
|
// source: grpc/binlog/v1/binarylog.proto
|
||||||
|
|
||||||
package grpc_binarylog_v1
|
package grpc_binarylog_v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
proto "github.com/golang/protobuf/proto"
|
||||||
duration "github.com/golang/protobuf/ptypes/duration"
|
|
||||||
timestamp "github.com/golang/protobuf/ptypes/timestamp"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
durationpb "google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
)
|
)
|
||||||
|
|
@ -243,7 +243,7 @@ type GrpcLogEntry struct {
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// The timestamp of the binary log message
|
// The timestamp of the binary log message
|
||||||
Timestamp *timestamp.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||||
// Uniquely identifies a call. The value must not be 0 in order to disambiguate
|
// Uniquely identifies a call. The value must not be 0 in order to disambiguate
|
||||||
// from an unset value.
|
// from an unset value.
|
||||||
// Each call may have several log entries, they will all have the same call_id.
|
// Each call may have several log entries, they will all have the same call_id.
|
||||||
|
|
@ -308,7 +308,7 @@ func (*GrpcLogEntry) Descriptor() ([]byte, []int) {
|
||||||
return file_grpc_binlog_v1_binarylog_proto_rawDescGZIP(), []int{0}
|
return file_grpc_binlog_v1_binarylog_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GrpcLogEntry) GetTimestamp() *timestamp.Timestamp {
|
func (x *GrpcLogEntry) GetTimestamp() *timestamppb.Timestamp {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Timestamp
|
return x.Timestamp
|
||||||
}
|
}
|
||||||
|
|
@ -439,7 +439,7 @@ type ClientHeader struct {
|
||||||
// <host> or <host>:<port> .
|
// <host> or <host>:<port> .
|
||||||
Authority string `protobuf:"bytes,3,opt,name=authority,proto3" json:"authority,omitempty"`
|
Authority string `protobuf:"bytes,3,opt,name=authority,proto3" json:"authority,omitempty"`
|
||||||
// the RPC timeout
|
// the RPC timeout
|
||||||
Timeout *duration.Duration `protobuf:"bytes,4,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
Timeout *durationpb.Duration `protobuf:"bytes,4,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientHeader) Reset() {
|
func (x *ClientHeader) Reset() {
|
||||||
|
|
@ -495,7 +495,7 @@ func (x *ClientHeader) GetAuthority() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientHeader) GetTimeout() *duration.Duration {
|
func (x *ClientHeader) GetTimeout() *durationpb.Duration {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Timeout
|
return x.Timeout
|
||||||
}
|
}
|
||||||
|
|
@ -1031,8 +1031,8 @@ var file_grpc_binlog_v1_binarylog_proto_goTypes = []interface{}{
|
||||||
(*Metadata)(nil), // 8: grpc.binarylog.v1.Metadata
|
(*Metadata)(nil), // 8: grpc.binarylog.v1.Metadata
|
||||||
(*MetadataEntry)(nil), // 9: grpc.binarylog.v1.MetadataEntry
|
(*MetadataEntry)(nil), // 9: grpc.binarylog.v1.MetadataEntry
|
||||||
(*Address)(nil), // 10: grpc.binarylog.v1.Address
|
(*Address)(nil), // 10: grpc.binarylog.v1.Address
|
||||||
(*timestamp.Timestamp)(nil), // 11: google.protobuf.Timestamp
|
(*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp
|
||||||
(*duration.Duration)(nil), // 12: google.protobuf.Duration
|
(*durationpb.Duration)(nil), // 12: google.protobuf.Duration
|
||||||
}
|
}
|
||||||
var file_grpc_binlog_v1_binarylog_proto_depIdxs = []int32{
|
var file_grpc_binlog_v1_binarylog_proto_depIdxs = []int32{
|
||||||
11, // 0: grpc.binarylog.v1.GrpcLogEntry.timestamp:type_name -> google.protobuf.Timestamp
|
11, // 0: grpc.binarylog.v1.GrpcLogEntry.timestamp:type_name -> google.protobuf.Timestamp
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -39,6 +38,7 @@ import (
|
||||||
"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/grpcutil"
|
"google.golang.org/grpc/internal/grpcutil"
|
||||||
|
iresolver "google.golang.org/grpc/internal/resolver"
|
||||||
"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"
|
||||||
|
|
@ -48,6 +48,7 @@ import (
|
||||||
_ "google.golang.org/grpc/balancer/roundrobin" // To register roundrobin.
|
_ "google.golang.org/grpc/balancer/roundrobin" // To register roundrobin.
|
||||||
_ "google.golang.org/grpc/internal/resolver/dns" // To register dns resolver.
|
_ "google.golang.org/grpc/internal/resolver/dns" // To register dns resolver.
|
||||||
_ "google.golang.org/grpc/internal/resolver/passthrough" // To register passthrough resolver.
|
_ "google.golang.org/grpc/internal/resolver/passthrough" // To register passthrough resolver.
|
||||||
|
_ "google.golang.org/grpc/internal/resolver/unix" // To register unix resolver.
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -104,6 +105,17 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) {
|
||||||
return DialContext(context.Background(), target, opts...)
|
return DialContext(context.Background(), target, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type defaultConfigSelector struct {
|
||||||
|
sc *ServiceConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dcs *defaultConfigSelector) SelectConfig(rpcInfo iresolver.RPCInfo) (*iresolver.RPCConfig, error) {
|
||||||
|
return &iresolver.RPCConfig{
|
||||||
|
Context: rpcInfo.Context,
|
||||||
|
MethodConfig: getMethodConfig(dcs.sc, rpcInfo.Method),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DialContext creates a client connection to the given target. By default, it's
|
// DialContext creates a client connection to the given target. By default, it's
|
||||||
// a non-blocking dial (the function won't wait for connections to be
|
// a non-blocking dial (the function won't wait for connections to be
|
||||||
// established, and connecting happens in the background). To make it a blocking
|
// established, and connecting happens in the background). To make it a blocking
|
||||||
|
|
@ -131,6 +143,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||||
firstResolveEvent: grpcsync.NewEvent(),
|
firstResolveEvent: grpcsync.NewEvent(),
|
||||||
}
|
}
|
||||||
cc.retryThrottler.Store((*retryThrottler)(nil))
|
cc.retryThrottler.Store((*retryThrottler)(nil))
|
||||||
|
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{nil})
|
||||||
cc.ctx, cc.cancel = context.WithCancel(context.Background())
|
cc.ctx, cc.cancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
|
|
@ -191,16 +204,6 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||||
}
|
}
|
||||||
cc.mkp = cc.dopts.copts.KeepaliveParams
|
cc.mkp = cc.dopts.copts.KeepaliveParams
|
||||||
|
|
||||||
if cc.dopts.copts.Dialer == nil {
|
|
||||||
cc.dopts.copts.Dialer = func(ctx context.Context, addr string) (net.Conn, error) {
|
|
||||||
network, addr := parseDialTarget(addr)
|
|
||||||
return (&net.Dialer{}).DialContext(ctx, network, addr)
|
|
||||||
}
|
|
||||||
if cc.dopts.withProxy {
|
|
||||||
cc.dopts.copts.Dialer = newProxyDialer(cc.dopts.copts.Dialer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cc.dopts.copts.UserAgent != "" {
|
if cc.dopts.copts.UserAgent != "" {
|
||||||
cc.dopts.copts.UserAgent += " " + grpcUA
|
cc.dopts.copts.UserAgent += " " + grpcUA
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -234,6 +237,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||||
case sc, ok := <-cc.dopts.scChan:
|
case sc, ok := <-cc.dopts.scChan:
|
||||||
if ok {
|
if ok {
|
||||||
cc.sc = &sc
|
cc.sc = &sc
|
||||||
|
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{&sc})
|
||||||
scSet = true
|
scSet = true
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -244,8 +248,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the resolver to use.
|
// Determine the resolver to use.
|
||||||
cc.parsedTarget = grpcutil.ParseTarget(cc.target)
|
cc.parsedTarget = grpcutil.ParseTarget(cc.target, cc.dopts.copts.Dialer != nil)
|
||||||
unixScheme := strings.HasPrefix(cc.target, "unix:")
|
|
||||||
channelz.Infof(logger, cc.channelzID, "parsed scheme: %q", cc.parsedTarget.Scheme)
|
channelz.Infof(logger, cc.channelzID, "parsed scheme: %q", cc.parsedTarget.Scheme)
|
||||||
resolverBuilder := cc.getResolver(cc.parsedTarget.Scheme)
|
resolverBuilder := cc.getResolver(cc.parsedTarget.Scheme)
|
||||||
if resolverBuilder == nil {
|
if resolverBuilder == nil {
|
||||||
|
|
@ -268,8 +271,10 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||||
cc.authority = creds.Info().ServerName
|
cc.authority = creds.Info().ServerName
|
||||||
} else if cc.dopts.insecure && cc.dopts.authority != "" {
|
} else if cc.dopts.insecure && cc.dopts.authority != "" {
|
||||||
cc.authority = cc.dopts.authority
|
cc.authority = cc.dopts.authority
|
||||||
} else if unixScheme {
|
} else if strings.HasPrefix(cc.target, "unix:") || strings.HasPrefix(cc.target, "unix-abstract:") {
|
||||||
cc.authority = "localhost"
|
cc.authority = "localhost"
|
||||||
|
} else if strings.HasPrefix(cc.parsedTarget.Endpoint, ":") {
|
||||||
|
cc.authority = "localhost" + cc.parsedTarget.Endpoint
|
||||||
} else {
|
} else {
|
||||||
// Use endpoint from "scheme://authority/endpoint" as the default
|
// Use endpoint from "scheme://authority/endpoint" as the default
|
||||||
// authority for ClientConn.
|
// authority for ClientConn.
|
||||||
|
|
@ -282,6 +287,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||||
case sc, ok := <-cc.dopts.scChan:
|
case sc, ok := <-cc.dopts.scChan:
|
||||||
if ok {
|
if ok {
|
||||||
cc.sc = &sc
|
cc.sc = &sc
|
||||||
|
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{&sc})
|
||||||
}
|
}
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, ctx.Err()
|
return nil, ctx.Err()
|
||||||
|
|
@ -299,6 +305,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||||
DialCreds: credsClone,
|
DialCreds: credsClone,
|
||||||
CredsBundle: cc.dopts.copts.CredsBundle,
|
CredsBundle: cc.dopts.copts.CredsBundle,
|
||||||
Dialer: cc.dopts.copts.Dialer,
|
Dialer: cc.dopts.copts.Dialer,
|
||||||
|
CustomUserAgent: cc.dopts.copts.UserAgent,
|
||||||
ChannelzParentID: cc.channelzID,
|
ChannelzParentID: cc.channelzID,
|
||||||
Target: cc.parsedTarget,
|
Target: cc.parsedTarget,
|
||||||
}
|
}
|
||||||
|
|
@ -487,6 +494,8 @@ type ClientConn struct {
|
||||||
balancerBuildOpts balancer.BuildOptions
|
balancerBuildOpts balancer.BuildOptions
|
||||||
blockingpicker *pickerWrapper
|
blockingpicker *pickerWrapper
|
||||||
|
|
||||||
|
safeConfigSelector iresolver.SafeConfigSelector
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
resolverWrapper *ccResolverWrapper
|
resolverWrapper *ccResolverWrapper
|
||||||
sc *ServiceConfig
|
sc *ServiceConfig
|
||||||
|
|
@ -547,6 +556,7 @@ func (cc *ClientConn) scWatcher() {
|
||||||
// TODO: load balance policy runtime change is ignored.
|
// TODO: load balance policy runtime change is ignored.
|
||||||
// We may revisit this decision in the future.
|
// We may revisit this decision in the future.
|
||||||
cc.sc = &sc
|
cc.sc = &sc
|
||||||
|
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{&sc})
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
case <-cc.ctx.Done():
|
case <-cc.ctx.Done():
|
||||||
return
|
return
|
||||||
|
|
@ -585,13 +595,13 @@ func init() {
|
||||||
|
|
||||||
func (cc *ClientConn) maybeApplyDefaultServiceConfig(addrs []resolver.Address) {
|
func (cc *ClientConn) maybeApplyDefaultServiceConfig(addrs []resolver.Address) {
|
||||||
if cc.sc != nil {
|
if cc.sc != nil {
|
||||||
cc.applyServiceConfigAndBalancer(cc.sc, addrs)
|
cc.applyServiceConfigAndBalancer(cc.sc, nil, addrs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if cc.dopts.defaultServiceConfig != nil {
|
if cc.dopts.defaultServiceConfig != nil {
|
||||||
cc.applyServiceConfigAndBalancer(cc.dopts.defaultServiceConfig, addrs)
|
cc.applyServiceConfigAndBalancer(cc.dopts.defaultServiceConfig, &defaultConfigSelector{cc.dopts.defaultServiceConfig}, addrs)
|
||||||
} else {
|
} else {
|
||||||
cc.applyServiceConfigAndBalancer(emptyServiceConfig, addrs)
|
cc.applyServiceConfigAndBalancer(emptyServiceConfig, &defaultConfigSelector{emptyServiceConfig}, addrs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -628,7 +638,15 @@ func (cc *ClientConn) updateResolverState(s resolver.State, err error) error {
|
||||||
// default, per the error handling design?
|
// default, per the error handling design?
|
||||||
} else {
|
} else {
|
||||||
if sc, ok := s.ServiceConfig.Config.(*ServiceConfig); s.ServiceConfig.Err == nil && ok {
|
if sc, ok := s.ServiceConfig.Config.(*ServiceConfig); s.ServiceConfig.Err == nil && ok {
|
||||||
cc.applyServiceConfigAndBalancer(sc, s.Addresses)
|
configSelector := iresolver.GetConfigSelector(s)
|
||||||
|
if configSelector != nil {
|
||||||
|
if len(s.ServiceConfig.Config.(*ServiceConfig).Methods) != 0 {
|
||||||
|
channelz.Infof(logger, cc.channelzID, "method configs in service config will be ignored due to presence of config selector")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
configSelector = &defaultConfigSelector{sc}
|
||||||
|
}
|
||||||
|
cc.applyServiceConfigAndBalancer(sc, configSelector, s.Addresses)
|
||||||
} else {
|
} else {
|
||||||
ret = balancer.ErrBadResolverState
|
ret = balancer.ErrBadResolverState
|
||||||
if cc.balancerWrapper == nil {
|
if cc.balancerWrapper == nil {
|
||||||
|
|
@ -638,6 +656,7 @@ func (cc *ClientConn) updateResolverState(s resolver.State, err error) error {
|
||||||
} else {
|
} else {
|
||||||
err = status.Errorf(codes.Unavailable, "illegal service config type: %T", s.ServiceConfig.Config)
|
err = status.Errorf(codes.Unavailable, "illegal service config type: %T", s.ServiceConfig.Config)
|
||||||
}
|
}
|
||||||
|
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{cc.sc})
|
||||||
cc.blockingpicker.updatePicker(base.NewErrPicker(err))
|
cc.blockingpicker.updatePicker(base.NewErrPicker(err))
|
||||||
cc.csMgr.updateState(connectivity.TransientFailure)
|
cc.csMgr.updateState(connectivity.TransientFailure)
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
@ -872,6 +891,20 @@ func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool {
|
||||||
return curAddrFound
|
return curAddrFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getMethodConfig(sc *ServiceConfig, method string) MethodConfig {
|
||||||
|
if sc == nil {
|
||||||
|
return MethodConfig{}
|
||||||
|
}
|
||||||
|
if m, ok := sc.Methods[method]; ok {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
i := strings.LastIndex(method, "/")
|
||||||
|
if m, ok := sc.Methods[method[:i+1]]; ok {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
return sc.Methods[""]
|
||||||
|
}
|
||||||
|
|
||||||
// GetMethodConfig gets the method config of the input method.
|
// GetMethodConfig gets the method config of the input method.
|
||||||
// If there's an exact match for input method (i.e. /service/method), we return
|
// If there's an exact match for input method (i.e. /service/method), we return
|
||||||
// the corresponding MethodConfig.
|
// the corresponding MethodConfig.
|
||||||
|
|
@ -884,17 +917,7 @@ func (cc *ClientConn) GetMethodConfig(method string) MethodConfig {
|
||||||
// TODO: Avoid the locking here.
|
// TODO: Avoid the locking here.
|
||||||
cc.mu.RLock()
|
cc.mu.RLock()
|
||||||
defer cc.mu.RUnlock()
|
defer cc.mu.RUnlock()
|
||||||
if cc.sc == nil {
|
return getMethodConfig(cc.sc, method)
|
||||||
return MethodConfig{}
|
|
||||||
}
|
|
||||||
if m, ok := cc.sc.Methods[method]; ok {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
i := strings.LastIndex(method, "/")
|
|
||||||
if m, ok := cc.sc.Methods[method[:i+1]]; ok {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
return cc.sc.Methods[""]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
|
func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
|
||||||
|
|
@ -917,12 +940,15 @@ func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method st
|
||||||
return t, done, nil
|
return t, done, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) applyServiceConfigAndBalancer(sc *ServiceConfig, addrs []resolver.Address) {
|
func (cc *ClientConn) applyServiceConfigAndBalancer(sc *ServiceConfig, configSelector iresolver.ConfigSelector, addrs []resolver.Address) {
|
||||||
if sc == nil {
|
if sc == nil {
|
||||||
// should never reach here.
|
// should never reach here.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cc.sc = sc
|
cc.sc = sc
|
||||||
|
if configSelector != nil {
|
||||||
|
cc.safeConfigSelector.UpdateConfigSelector(configSelector)
|
||||||
|
}
|
||||||
|
|
||||||
if cc.sc.retryThrottling != nil {
|
if cc.sc.retryThrottling != nil {
|
||||||
newThrottler := &retryThrottler{
|
newThrottler := &retryThrottler{
|
||||||
|
|
@ -1172,7 +1198,7 @@ func (ac *addrConn) resetTransport() {
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
if ac.state == connectivity.Shutdown {
|
if ac.state == connectivity.Shutdown {
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
newTr.Close()
|
newTr.Close(fmt.Errorf("reached connectivity state: SHUTDOWN"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ac.curAddr = addr
|
ac.curAddr = addr
|
||||||
|
|
@ -1304,7 +1330,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
|
||||||
select {
|
select {
|
||||||
case <-time.After(time.Until(connectDeadline)):
|
case <-time.After(time.Until(connectDeadline)):
|
||||||
// We didn't get the preface in time.
|
// We didn't get the preface in time.
|
||||||
newTr.Close()
|
newTr.Close(fmt.Errorf("failed to receive server preface within timeout"))
|
||||||
channelz.Warningf(logger, ac.channelzID, "grpc: addrConn.createTransport failed to connect to %v: didn't receive server preface in time. Reconnecting...", addr)
|
channelz.Warningf(logger, ac.channelzID, "grpc: addrConn.createTransport failed to connect to %v: didn't receive server preface in time. Reconnecting...", addr)
|
||||||
return nil, nil, errors.New("timed out waiting for server handshake")
|
return nil, nil, errors.New("timed out waiting for server handshake")
|
||||||
case <-prefaceReceived:
|
case <-prefaceReceived:
|
||||||
|
|
@ -1421,10 +1447,9 @@ func (ac *addrConn) getReadyTransport() (transport.ClientTransport, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// tearDown starts to tear down the addrConn.
|
// tearDown starts to tear down the addrConn.
|
||||||
// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in
|
//
|
||||||
// some edge cases (e.g., the caller opens and closes many addrConn's in a
|
// Note that tearDown doesn't remove ac from ac.cc.conns, so the addrConn struct
|
||||||
// tight loop.
|
// will leak. In most cases, call cc.removeAddrConn() instead.
|
||||||
// tearDown doesn't remove ac from ac.cc.conns.
|
|
||||||
func (ac *addrConn) tearDown(err error) {
|
func (ac *addrConn) tearDown(err error) {
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
if ac.state == connectivity.Shutdown {
|
if ac.state == connectivity.Shutdown {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import (
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"google.golang.org/grpc/attributes"
|
"google.golang.org/grpc/attributes"
|
||||||
"google.golang.org/grpc/internal"
|
icredentials "google.golang.org/grpc/internal/credentials"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PerRPCCredentials defines the common interface for the credentials which need to
|
// PerRPCCredentials defines the common interface for the credentials which need to
|
||||||
|
|
@ -58,9 +58,9 @@ type PerRPCCredentials interface {
|
||||||
type SecurityLevel int
|
type SecurityLevel int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Invalid indicates an invalid security level.
|
// InvalidSecurityLevel indicates an invalid security level.
|
||||||
// The zero SecurityLevel value is invalid for backward compatibility.
|
// The zero SecurityLevel value is invalid for backward compatibility.
|
||||||
Invalid SecurityLevel = iota
|
InvalidSecurityLevel SecurityLevel = iota
|
||||||
// NoSecurity indicates a connection is insecure.
|
// NoSecurity indicates a connection is insecure.
|
||||||
NoSecurity
|
NoSecurity
|
||||||
// IntegrityOnly indicates a connection only provides integrity protection.
|
// IntegrityOnly indicates a connection only provides integrity protection.
|
||||||
|
|
@ -92,7 +92,7 @@ type CommonAuthInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommonAuthInfo returns the pointer to CommonAuthInfo struct.
|
// GetCommonAuthInfo returns the pointer to CommonAuthInfo struct.
|
||||||
func (c *CommonAuthInfo) GetCommonAuthInfo() *CommonAuthInfo {
|
func (c CommonAuthInfo) GetCommonAuthInfo() CommonAuthInfo {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -188,15 +188,12 @@ type RequestInfo struct {
|
||||||
AuthInfo AuthInfo
|
AuthInfo AuthInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// requestInfoKey is a struct to be used as the key when attaching a RequestInfo to a context object.
|
|
||||||
type requestInfoKey struct{}
|
|
||||||
|
|
||||||
// RequestInfoFromContext extracts the RequestInfo from the context if it exists.
|
// RequestInfoFromContext extracts the RequestInfo from the context if it exists.
|
||||||
//
|
//
|
||||||
// This API is experimental.
|
// This API is experimental.
|
||||||
func RequestInfoFromContext(ctx context.Context) (ri RequestInfo, ok bool) {
|
func RequestInfoFromContext(ctx context.Context) (ri RequestInfo, ok bool) {
|
||||||
ri, ok = ctx.Value(requestInfoKey{}).(RequestInfo)
|
ri, ok = icredentials.RequestInfoFromContext(ctx).(RequestInfo)
|
||||||
return
|
return ri, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientHandshakeInfo holds data to be passed to ClientHandshake. This makes
|
// ClientHandshakeInfo holds data to be passed to ClientHandshake. This makes
|
||||||
|
|
@ -211,16 +208,12 @@ type ClientHandshakeInfo struct {
|
||||||
Attributes *attributes.Attributes
|
Attributes *attributes.Attributes
|
||||||
}
|
}
|
||||||
|
|
||||||
// clientHandshakeInfoKey is a struct used as the key to store
|
|
||||||
// ClientHandshakeInfo in a context.
|
|
||||||
type clientHandshakeInfoKey struct{}
|
|
||||||
|
|
||||||
// ClientHandshakeInfoFromContext returns the ClientHandshakeInfo struct stored
|
// ClientHandshakeInfoFromContext returns the ClientHandshakeInfo struct stored
|
||||||
// in ctx.
|
// in ctx.
|
||||||
//
|
//
|
||||||
// This API is experimental.
|
// This API is experimental.
|
||||||
func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo {
|
func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo {
|
||||||
chi, _ := ctx.Value(clientHandshakeInfoKey{}).(ClientHandshakeInfo)
|
chi, _ := icredentials.ClientHandshakeInfoFromContext(ctx).(ClientHandshakeInfo)
|
||||||
return chi
|
return chi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,17 +222,16 @@ func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo {
|
||||||
// or 3) CommonAuthInfo.SecurityLevel has an invalid zero value. For 2) and 3), it is for the purpose of backward-compatibility.
|
// or 3) CommonAuthInfo.SecurityLevel has an invalid zero value. For 2) and 3), it is for the purpose of backward-compatibility.
|
||||||
//
|
//
|
||||||
// This API is experimental.
|
// This API is experimental.
|
||||||
func CheckSecurityLevel(ctx context.Context, level SecurityLevel) error {
|
func CheckSecurityLevel(ai AuthInfo, level SecurityLevel) error {
|
||||||
type internalInfo interface {
|
type internalInfo interface {
|
||||||
GetCommonAuthInfo() *CommonAuthInfo
|
GetCommonAuthInfo() CommonAuthInfo
|
||||||
}
|
}
|
||||||
ri, _ := RequestInfoFromContext(ctx)
|
if ai == nil {
|
||||||
if ri.AuthInfo == nil {
|
return errors.New("AuthInfo is nil")
|
||||||
return errors.New("unable to obtain SecurityLevel from context")
|
|
||||||
}
|
}
|
||||||
if ci, ok := ri.AuthInfo.(internalInfo); ok {
|
if ci, ok := ai.(internalInfo); ok {
|
||||||
// CommonAuthInfo.SecurityLevel has an invalid value.
|
// CommonAuthInfo.SecurityLevel has an invalid value.
|
||||||
if ci.GetCommonAuthInfo().SecurityLevel == Invalid {
|
if ci.GetCommonAuthInfo().SecurityLevel == InvalidSecurityLevel {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if ci.GetCommonAuthInfo().SecurityLevel < level {
|
if ci.GetCommonAuthInfo().SecurityLevel < level {
|
||||||
|
|
@ -250,15 +242,6 @@ func CheckSecurityLevel(ctx context.Context, level SecurityLevel) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
internal.NewRequestInfoContext = func(ctx context.Context, ri RequestInfo) context.Context {
|
|
||||||
return context.WithValue(ctx, requestInfoKey{}, ri)
|
|
||||||
}
|
|
||||||
internal.NewClientHandshakeInfoContext = func(ctx context.Context, chi ClientHandshakeInfo) context.Context {
|
|
||||||
return context.WithValue(ctx, clientHandshakeInfoKey{}, chi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChannelzSecurityInfo defines the interface that security protocols should implement
|
// ChannelzSecurityInfo defines the interface that security protocols should implement
|
||||||
// in order to provide security info to channelz.
|
// in order to provide security info to channelz.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -66,12 +66,7 @@ type dialOptions struct {
|
||||||
minConnectTimeout func() time.Duration
|
minConnectTimeout func() time.Duration
|
||||||
defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
|
defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
|
||||||
defaultServiceConfigRawJSON *string
|
defaultServiceConfigRawJSON *string
|
||||||
// This is used by ccResolverWrapper to backoff between successive calls to
|
|
||||||
// resolver.ResolveNow(). The user will have no need to configure this, but
|
|
||||||
// we need to be able to configure this in tests.
|
|
||||||
resolveNowBackoff func(int) time.Duration
|
|
||||||
resolvers []resolver.Builder
|
resolvers []resolver.Builder
|
||||||
withProxy bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialOption configures how we set up the connection.
|
// DialOption configures how we set up the connection.
|
||||||
|
|
@ -325,7 +320,7 @@ func WithInsecure() DialOption {
|
||||||
// later release.
|
// later release.
|
||||||
func WithNoProxy() DialOption {
|
func WithNoProxy() DialOption {
|
||||||
return newFuncDialOption(func(o *dialOptions) {
|
return newFuncDialOption(func(o *dialOptions) {
|
||||||
o.withProxy = false
|
o.copts.UseProxy = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -595,9 +590,8 @@ func defaultDialOptions() dialOptions {
|
||||||
copts: transport.ConnectOptions{
|
copts: transport.ConnectOptions{
|
||||||
WriteBufferSize: defaultWriteBufSize,
|
WriteBufferSize: defaultWriteBufSize,
|
||||||
ReadBufferSize: defaultReadBufSize,
|
ReadBufferSize: defaultReadBufSize,
|
||||||
|
UseProxy: true,
|
||||||
},
|
},
|
||||||
resolveNowBackoff: internalbackoff.DefaultExponential.Backoff,
|
|
||||||
withProxy: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -612,16 +606,6 @@ func withMinConnectDeadline(f func() time.Duration) DialOption {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// withResolveNowBackoff specifies the function that clientconn uses to backoff
|
|
||||||
// between successive calls to resolver.ResolveNow().
|
|
||||||
//
|
|
||||||
// For testing purpose only.
|
|
||||||
func withResolveNowBackoff(f func(int) time.Duration) DialOption {
|
|
||||||
return newFuncDialOption(func(o *dialOptions) {
|
|
||||||
o.resolveNowBackoff = f
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithResolvers allows a list of resolver implementations to be registered
|
// WithResolvers allows a list of resolver implementations to be registered
|
||||||
// locally with the ClientConn without needing to be globally registered via
|
// locally with the ClientConn without needing to be globally registered via
|
||||||
// resolver.Register. They will be matched against the scheme used for the
|
// resolver.Register. They will be matched against the scheme used for the
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,7 @@
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"fmt"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"google.golang.org/grpc/encoding"
|
"google.golang.org/grpc/encoding"
|
||||||
|
|
@ -38,73 +37,22 @@ func init() {
|
||||||
// codec is a Codec implementation with protobuf. It is the default codec for gRPC.
|
// codec is a Codec implementation with protobuf. It is the default codec for gRPC.
|
||||||
type codec struct{}
|
type codec struct{}
|
||||||
|
|
||||||
type cachedProtoBuffer struct {
|
|
||||||
lastMarshaledSize uint32
|
|
||||||
proto.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func capToMaxInt32(val int) uint32 {
|
|
||||||
if val > math.MaxInt32 {
|
|
||||||
return uint32(math.MaxInt32)
|
|
||||||
}
|
|
||||||
return uint32(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshal(v interface{}, cb *cachedProtoBuffer) ([]byte, error) {
|
|
||||||
protoMsg := v.(proto.Message)
|
|
||||||
newSlice := make([]byte, 0, cb.lastMarshaledSize)
|
|
||||||
|
|
||||||
cb.SetBuf(newSlice)
|
|
||||||
cb.Reset()
|
|
||||||
if err := cb.Marshal(protoMsg); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
out := cb.Bytes()
|
|
||||||
cb.lastMarshaledSize = capToMaxInt32(len(out))
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (codec) Marshal(v interface{}) ([]byte, error) {
|
func (codec) Marshal(v interface{}) ([]byte, error) {
|
||||||
if pm, ok := v.(proto.Marshaler); ok {
|
vv, ok := v.(proto.Message)
|
||||||
// object can marshal itself, no need for buffer
|
if !ok {
|
||||||
return pm.Marshal()
|
return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v)
|
||||||
}
|
}
|
||||||
|
return proto.Marshal(vv)
|
||||||
cb := protoBufferPool.Get().(*cachedProtoBuffer)
|
|
||||||
out, err := marshal(v, cb)
|
|
||||||
|
|
||||||
// put back buffer and lose the ref to the slice
|
|
||||||
cb.SetBuf(nil)
|
|
||||||
protoBufferPool.Put(cb)
|
|
||||||
return out, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (codec) Unmarshal(data []byte, v interface{}) error {
|
func (codec) Unmarshal(data []byte, v interface{}) error {
|
||||||
protoMsg := v.(proto.Message)
|
vv, ok := v.(proto.Message)
|
||||||
protoMsg.Reset()
|
if !ok {
|
||||||
|
return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v)
|
||||||
if pu, ok := protoMsg.(proto.Unmarshaler); ok {
|
|
||||||
// object can unmarshal itself, no need for buffer
|
|
||||||
return pu.Unmarshal(data)
|
|
||||||
}
|
}
|
||||||
|
return proto.Unmarshal(data, vv)
|
||||||
cb := protoBufferPool.Get().(*cachedProtoBuffer)
|
|
||||||
cb.SetBuf(data)
|
|
||||||
err := cb.Unmarshal(protoMsg)
|
|
||||||
cb.SetBuf(nil)
|
|
||||||
protoBufferPool.Put(cb)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (codec) Name() string {
|
func (codec) Name() string {
|
||||||
return Name
|
return Name
|
||||||
}
|
}
|
||||||
|
|
||||||
var protoBufferPool = &sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return &cachedProtoBuffer{
|
|
||||||
Buffer: proto.Buffer{},
|
|
||||||
lastMarshaledSize: 16,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ module google.golang.org/grpc
|
||||||
go 1.11
|
go 1.11
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
||||||
github.com/golang/protobuf v1.4.1
|
github.com/golang/protobuf v1.4.2
|
||||||
github.com/google/go-cmp v0.5.0
|
github.com/google/go-cmp v0.5.0
|
||||||
github.com/google/uuid v1.1.2
|
github.com/google/uuid v1.1.2
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,17 @@
|
||||||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||||
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/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
|
|
@ -21,18 +24,23 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
|
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
|
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
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=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
|
@ -63,7 +71,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
|
||||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
|
@ -77,8 +84,13 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
||||||
|
|
@ -25,25 +25,41 @@ import (
|
||||||
// UnaryInvoker is called by UnaryClientInterceptor to complete RPCs.
|
// UnaryInvoker is called by UnaryClientInterceptor to complete RPCs.
|
||||||
type UnaryInvoker func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error
|
type UnaryInvoker func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error
|
||||||
|
|
||||||
// UnaryClientInterceptor intercepts the execution of a unary RPC on the client. invoker is the handler to complete the RPC
|
// UnaryClientInterceptor intercepts the execution of a unary RPC on the client.
|
||||||
// and it is the responsibility of the interceptor to call it.
|
// Unary interceptors can be specified as a DialOption, using
|
||||||
|
// WithUnaryInterceptor() or WithChainUnaryInterceptor(), when creating a
|
||||||
|
// ClientConn. When a unary interceptor(s) is set on a ClientConn, gRPC
|
||||||
|
// delegates all unary RPC invocations to the interceptor, and it is the
|
||||||
|
// responsibility of the interceptor to call invoker to complete the processing
|
||||||
|
// of the RPC.
|
||||||
//
|
//
|
||||||
// Experimental
|
// method is the RPC name. req and reply are the corresponding request and
|
||||||
|
// response messages. cc is the ClientConn on which the RPC was invoked. invoker
|
||||||
|
// is the handler to complete the RPC and it is the responsibility of the
|
||||||
|
// interceptor to call it. opts contain all applicable call options, including
|
||||||
|
// defaults from the ClientConn as well as per-call options.
|
||||||
//
|
//
|
||||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
// The returned error must be compatible with the status package.
|
||||||
// later release.
|
|
||||||
type UnaryClientInterceptor func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error
|
type UnaryClientInterceptor func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error
|
||||||
|
|
||||||
// Streamer is called by StreamClientInterceptor to create a ClientStream.
|
// Streamer is called by StreamClientInterceptor to create a ClientStream.
|
||||||
type Streamer func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error)
|
type Streamer func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error)
|
||||||
|
|
||||||
// StreamClientInterceptor intercepts the creation of ClientStream. It may return a custom ClientStream to intercept all I/O
|
// StreamClientInterceptor intercepts the creation of a ClientStream. Stream
|
||||||
// operations. streamer is the handler to create a ClientStream and it is the responsibility of the interceptor to call it.
|
// interceptors can be specified as a DialOption, using WithStreamInterceptor()
|
||||||
|
// or WithChainStreamInterceptor(), when creating a ClientConn. When a stream
|
||||||
|
// interceptor(s) is set on the ClientConn, gRPC delegates all stream creations
|
||||||
|
// to the interceptor, and it is the responsibility of the interceptor to call
|
||||||
|
// streamer.
|
||||||
//
|
//
|
||||||
// Experimental
|
// desc contains a description of the stream. cc is the ClientConn on which the
|
||||||
|
// RPC was invoked. streamer is the handler to create a ClientStream and it is
|
||||||
|
// the responsibility of the interceptor to call it. opts contain all applicable
|
||||||
|
// call options, including defaults from the ClientConn as well as per-call
|
||||||
|
// options.
|
||||||
//
|
//
|
||||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
// StreamClientInterceptor may return a custom ClientStream to intercept all I/O
|
||||||
// later release.
|
// operations. The returned error must be compatible with the status package.
|
||||||
type StreamClientInterceptor func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, streamer Streamer, opts ...CallOption) (ClientStream, error)
|
type StreamClientInterceptor func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, streamer Streamer, opts ...CallOption) (ClientStream, error)
|
||||||
|
|
||||||
// UnaryServerInfo consists of various information about a unary RPC on
|
// UnaryServerInfo consists of various information about a unary RPC on
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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 credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// requestInfoKey is a struct to be used as the key to store RequestInfo in a
|
||||||
|
// context.
|
||||||
|
type requestInfoKey struct{}
|
||||||
|
|
||||||
|
// NewRequestInfoContext creates a context with ri.
|
||||||
|
func NewRequestInfoContext(ctx context.Context, ri interface{}) context.Context {
|
||||||
|
return context.WithValue(ctx, requestInfoKey{}, ri)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestInfoFromContext extracts the RequestInfo from ctx.
|
||||||
|
func RequestInfoFromContext(ctx context.Context) interface{} {
|
||||||
|
return ctx.Value(requestInfoKey{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// clientHandshakeInfoKey is a struct used as the key to store
|
||||||
|
// ClientHandshakeInfo in a context.
|
||||||
|
type clientHandshakeInfoKey struct{}
|
||||||
|
|
||||||
|
// ClientHandshakeInfoFromContext extracts the ClientHandshakeInfo from ctx.
|
||||||
|
func ClientHandshakeInfoFromContext(ctx context.Context) interface{} {
|
||||||
|
return ctx.Value(clientHandshakeInfoKey{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClientHandshakeInfoContext creates a context with chi.
|
||||||
|
func NewClientHandshakeInfoContext(ctx context.Context, chi interface{}) context.Context {
|
||||||
|
return context.WithValue(ctx, clientHandshakeInfoKey{}, chi)
|
||||||
|
}
|
||||||
|
|
@ -37,19 +37,53 @@ func split2(s, sep string) (string, string, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseTarget splits target into a resolver.Target struct containing scheme,
|
// ParseTarget splits target into a resolver.Target struct containing scheme,
|
||||||
// authority and endpoint.
|
// 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, it returns {Endpoint:
|
// If target is not a valid scheme://authority/endpoint as specified in
|
||||||
// target}.
|
// https://github.com/grpc/grpc/blob/master/doc/naming.md,
|
||||||
func ParseTarget(target string) (ret resolver.Target) {
|
// it returns {Endpoint: target}.
|
||||||
|
func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) {
|
||||||
var ok bool
|
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, "://")
|
ret.Scheme, ret.Endpoint, ok = split2(target, "://")
|
||||||
if !ok {
|
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}
|
return resolver.Target{Endpoint: target}
|
||||||
}
|
}
|
||||||
ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/")
|
ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/")
|
||||||
if !ok {
|
if !ok {
|
||||||
return resolver.Target{Endpoint: target}
|
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
|
return ret
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,6 @@ 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
|
||||||
// NewRequestInfoContext creates a new context based on the argument context attaching
|
|
||||||
// the passed in RequestInfo to the new context.
|
|
||||||
NewRequestInfoContext interface{} // func(context.Context, credentials.RequestInfo) context.Context
|
|
||||||
// NewClientHandshakeInfoContext returns a copy of the input context with
|
|
||||||
// the passed in ClientHandshakeInfo struct added to it.
|
|
||||||
NewClientHandshakeInfoContext interface{} // func(context.Context, credentials.ClientHandshakeInfo) context.Context
|
|
||||||
// ParseServiceConfigForTesting is for creating a fake
|
// ParseServiceConfigForTesting is for creating a fake
|
||||||
// ClientConn for resolver testing only
|
// ClientConn for resolver testing only
|
||||||
ParseServiceConfigForTesting interface{} // func(string) *serviceconfig.ParseResult
|
ParseServiceConfigForTesting interface{} // func(string) *serviceconfig.ParseResult
|
||||||
|
|
@ -57,6 +51,19 @@ var (
|
||||||
// bootstrap code while parsing certificate provider configs in the
|
// bootstrap code while parsing certificate provider configs in the
|
||||||
// bootstrap file.
|
// bootstrap file.
|
||||||
GetCertificateProviderBuilder interface{} // func(string) certprovider.Builder
|
GetCertificateProviderBuilder interface{} // func(string) certprovider.Builder
|
||||||
|
// GetXDSHandshakeInfoForTesting returns a pointer to the xds.HandshakeInfo
|
||||||
|
// stored in the passed in attributes. This is set by
|
||||||
|
// credentials/xds/xds.go.
|
||||||
|
GetXDSHandshakeInfoForTesting interface{} // func (*attributes.Attributes) *xds.HandshakeInfo
|
||||||
|
// GetServerCredentials returns the transport credentials configured on a
|
||||||
|
// gRPC server. An xDS-enabled server needs to know what type of credentials
|
||||||
|
// is configured on the underlying gRPC server. This is set by server.go.
|
||||||
|
GetServerCredentials interface{} // func (*grpc.Server) credentials.TransportCredentials
|
||||||
|
// DrainServerTransports initiates a graceful close of existing connections
|
||||||
|
// on a gRPC server accepted on the provided listener address. An
|
||||||
|
// xDS-enabled server invokes this method on a grpc.Server when a particular
|
||||||
|
// listener moves to "not-serving" mode.
|
||||||
|
DrainServerTransports interface{} // func(*grpc.Server, string)
|
||||||
)
|
)
|
||||||
|
|
||||||
// HealthChecker defines the signature of the client-side LB channel health checking function.
|
// HealthChecker defines the signature of the client-side LB channel health checking function.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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 metadata contains functions to set and get metadata from addresses.
|
||||||
|
//
|
||||||
|
// This package is experimental.
|
||||||
|
package metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mdKeyType string
|
||||||
|
|
||||||
|
const mdKey = mdKeyType("grpc.internal.address.metadata")
|
||||||
|
|
||||||
|
// Get returns the metadata of addr.
|
||||||
|
func Get(addr resolver.Address) metadata.MD {
|
||||||
|
attrs := addr.Attributes
|
||||||
|
if attrs == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
md, _ := attrs.Value(mdKey).(metadata.MD)
|
||||||
|
return md
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets (overrides) the metadata in addr.
|
||||||
|
//
|
||||||
|
// When a SubConn is created with this address, the RPCs sent on it will all
|
||||||
|
// have this metadata.
|
||||||
|
func Set(addr resolver.Address, md metadata.MD) resolver.Address {
|
||||||
|
addr.Attributes = addr.Attributes.WithValues(mdKey, md)
|
||||||
|
return addr
|
||||||
|
}
|
||||||
164
vendor/google.golang.org/grpc/internal/resolver/config_selector.go
generated
vendored
Normal file
164
vendor/google.golang.org/grpc/internal/resolver/config_selector.go
generated
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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 resolver provides internal resolver-related functionality.
|
||||||
|
package resolver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"google.golang.org/grpc/internal/serviceconfig"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConfigSelector controls what configuration to use for every RPC.
|
||||||
|
type ConfigSelector interface {
|
||||||
|
// Selects the configuration for the RPC, or terminates it using the error.
|
||||||
|
// This error will be converted by the gRPC library to a status error with
|
||||||
|
// code UNKNOWN if it is not returned as a status error.
|
||||||
|
SelectConfig(RPCInfo) (*RPCConfig, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCInfo contains RPC information needed by a ConfigSelector.
|
||||||
|
type RPCInfo struct {
|
||||||
|
// Context is the user's context for the RPC and contains headers and
|
||||||
|
// application timeout. It is passed for interception purposes and for
|
||||||
|
// efficiency reasons. SelectConfig should not be blocking.
|
||||||
|
Context context.Context
|
||||||
|
Method string // i.e. "/Service/Method"
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCConfig describes the configuration to use for each RPC.
|
||||||
|
type RPCConfig struct {
|
||||||
|
// The context to use for the remainder of the RPC; can pass info to LB
|
||||||
|
// policy or affect timeout or metadata.
|
||||||
|
Context context.Context
|
||||||
|
MethodConfig serviceconfig.MethodConfig // configuration to use for this RPC
|
||||||
|
OnCommitted func() // Called when the RPC has been committed (retries no longer possible)
|
||||||
|
Interceptor ClientInterceptor
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientStream is the same as grpc.ClientStream, but defined here for circular
|
||||||
|
// dependency reasons.
|
||||||
|
type ClientStream interface {
|
||||||
|
// Header returns the header metadata received from the server if there
|
||||||
|
// is any. It blocks if the metadata is not ready to read.
|
||||||
|
Header() (metadata.MD, error)
|
||||||
|
// Trailer returns the trailer metadata from the server, if there is any.
|
||||||
|
// It must only be called after stream.CloseAndRecv has returned, or
|
||||||
|
// stream.Recv has returned a non-nil error (including io.EOF).
|
||||||
|
Trailer() metadata.MD
|
||||||
|
// CloseSend closes the send direction of the stream. It closes the stream
|
||||||
|
// when non-nil error is met. It is also not safe to call CloseSend
|
||||||
|
// concurrently with SendMsg.
|
||||||
|
CloseSend() error
|
||||||
|
// Context returns the context for this stream.
|
||||||
|
//
|
||||||
|
// It should not be called until after Header or RecvMsg has returned. Once
|
||||||
|
// called, subsequent client-side retries are disabled.
|
||||||
|
Context() context.Context
|
||||||
|
// SendMsg is generally called by generated code. On error, SendMsg aborts
|
||||||
|
// the stream. If the error was generated by the client, the status is
|
||||||
|
// returned directly; otherwise, io.EOF is returned and the status of
|
||||||
|
// the stream may be discovered using RecvMsg.
|
||||||
|
//
|
||||||
|
// SendMsg blocks until:
|
||||||
|
// - There is sufficient flow control to schedule m with the transport, or
|
||||||
|
// - The stream is done, or
|
||||||
|
// - The stream breaks.
|
||||||
|
//
|
||||||
|
// SendMsg does not wait until the message is received by the server. An
|
||||||
|
// untimely stream closure may result in lost messages. To ensure delivery,
|
||||||
|
// users should ensure the RPC completed successfully using RecvMsg.
|
||||||
|
//
|
||||||
|
// It is safe to have a goroutine calling SendMsg and another goroutine
|
||||||
|
// calling RecvMsg on the same stream at the same time, but it is not safe
|
||||||
|
// to call SendMsg on the same stream in different goroutines. It is also
|
||||||
|
// not safe to call CloseSend concurrently with SendMsg.
|
||||||
|
SendMsg(m interface{}) error
|
||||||
|
// RecvMsg blocks until it receives a message into m or the stream is
|
||||||
|
// done. It returns io.EOF when the stream completes successfully. On
|
||||||
|
// any other error, the stream is aborted and the error contains the RPC
|
||||||
|
// status.
|
||||||
|
//
|
||||||
|
// It is safe to have a goroutine calling SendMsg and another goroutine
|
||||||
|
// calling RecvMsg on the same stream at the same time, but it is not
|
||||||
|
// safe to call RecvMsg on the same stream in different goroutines.
|
||||||
|
RecvMsg(m interface{}) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientInterceptor is an interceptor for gRPC client streams.
|
||||||
|
type ClientInterceptor interface {
|
||||||
|
// NewStream produces a ClientStream for an RPC which may optionally use
|
||||||
|
// the provided function to produce a stream for delegation. Note:
|
||||||
|
// RPCInfo.Context should not be used (will be nil).
|
||||||
|
//
|
||||||
|
// done is invoked when the RPC is finished using its connection, or could
|
||||||
|
// not be assigned a connection. RPC operations may still occur on
|
||||||
|
// ClientStream after done is called, since the interceptor is invoked by
|
||||||
|
// application-layer operations. done must never be nil when called.
|
||||||
|
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.
|
||||||
|
type ServerInterceptor interface {
|
||||||
|
notDefined()
|
||||||
|
}
|
||||||
|
|
||||||
|
type csKeyType string
|
||||||
|
|
||||||
|
const csKey = csKeyType("grpc.internal.resolver.configSelector")
|
||||||
|
|
||||||
|
// SetConfigSelector sets the config selector in state and returns the new
|
||||||
|
// state.
|
||||||
|
func SetConfigSelector(state resolver.State, cs ConfigSelector) resolver.State {
|
||||||
|
state.Attributes = state.Attributes.WithValues(csKey, cs)
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfigSelector retrieves the config selector from state, if present, and
|
||||||
|
// returns it or nil if absent.
|
||||||
|
func GetConfigSelector(state resolver.State) ConfigSelector {
|
||||||
|
cs, _ := state.Attributes.Value(csKey).(ConfigSelector)
|
||||||
|
return cs
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeConfigSelector allows for safe switching of ConfigSelector
|
||||||
|
// implementations such that previous values are guaranteed to not be in use
|
||||||
|
// when UpdateConfigSelector returns.
|
||||||
|
type SafeConfigSelector struct {
|
||||||
|
mu sync.RWMutex
|
||||||
|
cs ConfigSelector
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateConfigSelector swaps to the provided ConfigSelector and blocks until
|
||||||
|
// all uses of the previous ConfigSelector have completed.
|
||||||
|
func (scs *SafeConfigSelector) UpdateConfigSelector(cs ConfigSelector) {
|
||||||
|
scs.mu.Lock()
|
||||||
|
defer scs.mu.Unlock()
|
||||||
|
scs.cs = cs
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectConfig defers to the current ConfigSelector in scs.
|
||||||
|
func (scs *SafeConfigSelector) SelectConfig(r RPCInfo) (*RPCConfig, error) {
|
||||||
|
scs.mu.RLock()
|
||||||
|
defer scs.mu.RUnlock()
|
||||||
|
return scs.cs.SelectConfig(r)
|
||||||
|
}
|
||||||
|
|
@ -34,6 +34,7 @@ import (
|
||||||
|
|
||||||
grpclbstate "google.golang.org/grpc/balancer/grpclb/state"
|
grpclbstate "google.golang.org/grpc/balancer/grpclb/state"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
|
"google.golang.org/grpc/internal/backoff"
|
||||||
"google.golang.org/grpc/internal/envconfig"
|
"google.golang.org/grpc/internal/envconfig"
|
||||||
"google.golang.org/grpc/internal/grpcrand"
|
"google.golang.org/grpc/internal/grpcrand"
|
||||||
"google.golang.org/grpc/resolver"
|
"google.golang.org/grpc/resolver"
|
||||||
|
|
@ -46,6 +47,13 @@ var EnableSRVLookups = false
|
||||||
|
|
||||||
var logger = grpclog.Component("dns")
|
var logger = grpclog.Component("dns")
|
||||||
|
|
||||||
|
// Globals to stub out in tests. TODO: Perhaps these two can be combined into a
|
||||||
|
// single variable for testing the resolver?
|
||||||
|
var (
|
||||||
|
newTimer = time.NewTimer
|
||||||
|
newTimerDNSResRate = time.NewTimer
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
resolver.Register(NewBuilder())
|
resolver.Register(NewBuilder())
|
||||||
}
|
}
|
||||||
|
|
@ -143,7 +151,6 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
|
||||||
|
|
||||||
d.wg.Add(1)
|
d.wg.Add(1)
|
||||||
go d.watcher()
|
go d.watcher()
|
||||||
d.ResolveNow(resolver.ResolveNowOptions{})
|
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,28 +208,38 @@ func (d *dnsResolver) Close() {
|
||||||
|
|
||||||
func (d *dnsResolver) watcher() {
|
func (d *dnsResolver) watcher() {
|
||||||
defer d.wg.Done()
|
defer d.wg.Done()
|
||||||
|
backoffIndex := 1
|
||||||
for {
|
for {
|
||||||
|
state, err := d.lookup()
|
||||||
|
if err != nil {
|
||||||
|
// Report error to the underlying grpc.ClientConn.
|
||||||
|
d.cc.ReportError(err)
|
||||||
|
} else {
|
||||||
|
err = d.cc.UpdateState(*state)
|
||||||
|
}
|
||||||
|
|
||||||
|
var timer *time.Timer
|
||||||
|
if err == nil {
|
||||||
|
// Success resolving, wait for the next ResolveNow. However, also wait 30 seconds at the very least
|
||||||
|
// to prevent constantly re-resolving.
|
||||||
|
backoffIndex = 1
|
||||||
|
timer = newTimerDNSResRate(minDNSResRate)
|
||||||
select {
|
select {
|
||||||
case <-d.ctx.Done():
|
case <-d.ctx.Done():
|
||||||
|
timer.Stop()
|
||||||
return
|
return
|
||||||
case <-d.rn:
|
case <-d.rn:
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := d.lookup()
|
|
||||||
if err != nil {
|
|
||||||
d.cc.ReportError(err)
|
|
||||||
} else {
|
} else {
|
||||||
d.cc.UpdateState(*state)
|
// Poll on an error found in DNS Resolver or an error received from ClientConn.
|
||||||
|
timer = newTimer(backoff.DefaultExponential.Backoff(backoffIndex))
|
||||||
|
backoffIndex++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sleep to prevent excessive re-resolutions. Incoming resolution requests
|
|
||||||
// will be queued in d.rn.
|
|
||||||
t := time.NewTimer(minDNSResRate)
|
|
||||||
select {
|
select {
|
||||||
case <-t.C:
|
|
||||||
case <-d.ctx.Done():
|
case <-d.ctx.Done():
|
||||||
t.Stop()
|
timer.Stop()
|
||||||
return
|
return
|
||||||
|
case <-timer.C:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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 unix implements a resolver for unix targets.
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"google.golang.org/grpc/internal/transport/networktype"
|
||||||
|
"google.golang.org/grpc/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
const unixScheme = "unix"
|
||||||
|
const unixAbstractScheme = "unix-abstract"
|
||||||
|
|
||||||
|
type builder struct {
|
||||||
|
scheme string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
|
||||||
|
if target.Authority != "" {
|
||||||
|
return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority)
|
||||||
|
}
|
||||||
|
addr := resolver.Address{Addr: target.Endpoint}
|
||||||
|
if b.scheme == unixAbstractScheme {
|
||||||
|
// prepend "\x00" to address for unix-abstract
|
||||||
|
addr.Addr = "\x00" + addr.Addr
|
||||||
|
}
|
||||||
|
cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(addr, "unix")}})
|
||||||
|
return &nopResolver{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) Scheme() string {
|
||||||
|
return b.scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
type nopResolver struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nopResolver) ResolveNow(resolver.ResolveNowOptions) {}
|
||||||
|
|
||||||
|
func (*nopResolver) Close() {}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
resolver.Register(&builder{scheme: unixScheme})
|
||||||
|
resolver.Register(&builder{scheme: unixAbstractScheme})
|
||||||
|
}
|
||||||
|
|
@ -22,8 +22,10 @@ package serviceconfig
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"google.golang.org/grpc/balancer"
|
"google.golang.org/grpc/balancer"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
externalserviceconfig "google.golang.org/grpc/serviceconfig"
|
externalserviceconfig "google.golang.org/grpc/serviceconfig"
|
||||||
)
|
)
|
||||||
|
|
@ -44,6 +46,22 @@ type BalancerConfig struct {
|
||||||
|
|
||||||
type intermediateBalancerConfig []map[string]json.RawMessage
|
type intermediateBalancerConfig []map[string]json.RawMessage
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
//
|
||||||
|
// It marshals the balancer and config into a length-1 slice
|
||||||
|
// ([]map[string]config).
|
||||||
|
func (bc *BalancerConfig) MarshalJSON() ([]byte, error) {
|
||||||
|
if bc.Config == nil {
|
||||||
|
// If config is nil, return empty config `{}`.
|
||||||
|
return []byte(fmt.Sprintf(`[{%q: %v}]`, bc.Name, "{}")), nil
|
||||||
|
}
|
||||||
|
c, err := json.Marshal(bc.Config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return []byte(fmt.Sprintf(`[{%q: %s}]`, bc.Name, c)), nil
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
//
|
//
|
||||||
// ServiceConfig contains a list of loadBalancingConfigs, each with a name and
|
// ServiceConfig contains a list of loadBalancingConfigs, each with a name and
|
||||||
|
|
@ -104,3 +122,57 @@ func (bc *BalancerConfig) UnmarshalJSON(b []byte) error {
|
||||||
// case.
|
// case.
|
||||||
return fmt.Errorf("invalid loadBalancingConfig: no supported policies found")
|
return fmt.Errorf("invalid loadBalancingConfig: no supported policies found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MethodConfig defines the configuration recommended by the service providers for a
|
||||||
|
// particular method.
|
||||||
|
type MethodConfig struct {
|
||||||
|
// WaitForReady indicates whether RPCs sent to this method should wait until
|
||||||
|
// the connection is ready by default (!failfast). The value specified via the
|
||||||
|
// gRPC client API will override the value set here.
|
||||||
|
WaitForReady *bool
|
||||||
|
// Timeout is the default timeout for RPCs sent to this method. The actual
|
||||||
|
// deadline used will be the minimum of the value specified here and the value
|
||||||
|
// set by the application via the gRPC client API. If either one is not set,
|
||||||
|
// then the other will be used. If neither is set, then the RPC has no deadline.
|
||||||
|
Timeout *time.Duration
|
||||||
|
// MaxReqSize is the maximum allowed payload size for an individual request in a
|
||||||
|
// stream (client->server) in bytes. The size which is measured is the serialized
|
||||||
|
// payload after per-message compression (but before stream compression) in bytes.
|
||||||
|
// The actual value used is the minimum of the value specified here and the value set
|
||||||
|
// by the application via the gRPC client API. If either one is not set, then the other
|
||||||
|
// will be used. If neither is set, then the built-in default is used.
|
||||||
|
MaxReqSize *int
|
||||||
|
// MaxRespSize is the maximum allowed payload size for an individual response in a
|
||||||
|
// stream (server->client) in bytes.
|
||||||
|
MaxRespSize *int
|
||||||
|
// RetryPolicy configures retry options for the method.
|
||||||
|
RetryPolicy *RetryPolicy
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryPolicy defines the go-native version of the retry policy defined by the
|
||||||
|
// service config here:
|
||||||
|
// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#integration-with-service-config
|
||||||
|
type RetryPolicy struct {
|
||||||
|
// MaxAttempts is the maximum number of attempts, including the original RPC.
|
||||||
|
//
|
||||||
|
// This field is required and must be two or greater.
|
||||||
|
MaxAttempts int
|
||||||
|
|
||||||
|
// Exponential backoff parameters. The initial retry attempt will occur at
|
||||||
|
// random(0, initialBackoff). In general, the nth attempt will occur at
|
||||||
|
// random(0,
|
||||||
|
// min(initialBackoff*backoffMultiplier**(n-1), maxBackoff)).
|
||||||
|
//
|
||||||
|
// These fields are required and must be greater than zero.
|
||||||
|
InitialBackoff time.Duration
|
||||||
|
MaxBackoff time.Duration
|
||||||
|
BackoffMultiplier float64
|
||||||
|
|
||||||
|
// The set of status codes which may be retried.
|
||||||
|
//
|
||||||
|
// Status codes are specified as strings, e.g., "UNAVAILABLE".
|
||||||
|
//
|
||||||
|
// This field is required and must be non-empty.
|
||||||
|
// Note: a set is used to store this for easy lookup.
|
||||||
|
RetryableStatusCodes map[codes.Code]bool
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,25 +44,23 @@ func GetCPUTime() int64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rusage is an alias for syscall.Rusage under linux environment.
|
// Rusage is an alias for syscall.Rusage under linux environment.
|
||||||
type Rusage syscall.Rusage
|
type Rusage = syscall.Rusage
|
||||||
|
|
||||||
// GetRusage returns the resource usage of current process.
|
// GetRusage returns the resource usage of current process.
|
||||||
func GetRusage() (rusage *Rusage) {
|
func GetRusage() *Rusage {
|
||||||
rusage = new(Rusage)
|
rusage := new(Rusage)
|
||||||
syscall.Getrusage(syscall.RUSAGE_SELF, (*syscall.Rusage)(rusage))
|
syscall.Getrusage(syscall.RUSAGE_SELF, rusage)
|
||||||
return
|
return rusage
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// between two Rusage structs.
|
||||||
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
|
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
|
||||||
f := (*syscall.Rusage)(first)
|
|
||||||
l := (*syscall.Rusage)(latest)
|
|
||||||
var (
|
var (
|
||||||
utimeDiffs = l.Utime.Sec - f.Utime.Sec
|
utimeDiffs = latest.Utime.Sec - first.Utime.Sec
|
||||||
utimeDiffus = l.Utime.Usec - f.Utime.Usec
|
utimeDiffus = latest.Utime.Usec - first.Utime.Usec
|
||||||
stimeDiffs = l.Stime.Sec - f.Stime.Sec
|
stimeDiffs = latest.Stime.Sec - first.Stime.Sec
|
||||||
stimeDiffus = l.Stime.Usec - f.Stime.Usec
|
stimeDiffus = latest.Stime.Usec - first.Stime.Usec
|
||||||
)
|
)
|
||||||
|
|
||||||
uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
|
uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ func GetCPUTime() int64 {
|
||||||
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 or appengine environment.
|
||||||
func GetRusage() (rusage *Rusage) {
|
func GetRusage() *Rusage {
|
||||||
log()
|
log()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,17 @@ package transport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"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/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
|
var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
|
||||||
|
|
@ -128,6 +132,14 @@ 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 {
|
||||||
|
streamID uint32
|
||||||
|
contentSubtype string
|
||||||
|
status *status.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*earlyAbortStream) isTransportResponseFrame() bool { return false }
|
||||||
|
|
||||||
type dataFrame struct {
|
type dataFrame struct {
|
||||||
streamID uint32
|
streamID uint32
|
||||||
endStream bool
|
endStream bool
|
||||||
|
|
@ -749,6 +761,24 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *loopyWriter) earlyAbortStreamHandler(eas *earlyAbortStream) error {
|
||||||
|
if l.side == clientSide {
|
||||||
|
return errors.New("earlyAbortStream not handled on client")
|
||||||
|
}
|
||||||
|
|
||||||
|
headerFields := []hpack.HeaderField{
|
||||||
|
{Name: ":status", Value: "200"},
|
||||||
|
{Name: "content-type", Value: grpcutil.ContentType(eas.contentSubtype)},
|
||||||
|
{Name: "grpc-status", Value: strconv.Itoa(int(eas.status.Code()))},
|
||||||
|
{Name: "grpc-message", Value: encodeGrpcMessage(eas.status.Message())},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := l.writeHeader(eas.streamID, true, headerFields, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error {
|
func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error {
|
||||||
if l.side == clientSide {
|
if l.side == clientSide {
|
||||||
l.draining = true
|
l.draining = true
|
||||||
|
|
@ -787,6 +817,8 @@ func (l *loopyWriter) handle(i interface{}) error {
|
||||||
return l.registerStreamHandler(i)
|
return l.registerStreamHandler(i)
|
||||||
case *cleanupStream:
|
case *cleanupStream:
|
||||||
return l.cleanupStreamHandler(i)
|
return l.cleanupStreamHandler(i)
|
||||||
|
case *earlyAbortStream:
|
||||||
|
return l.earlyAbortStreamHandler(i)
|
||||||
case *incomingGoAway:
|
case *incomingGoAway:
|
||||||
return l.incomingGoAwayHandler(i)
|
return l.incomingGoAwayHandler(i)
|
||||||
case *dataFrame:
|
case *dataFrame:
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,14 @@ 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/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
"google.golang.org/grpc/internal"
|
|
||||||
"google.golang.org/grpc/internal/channelz"
|
"google.golang.org/grpc/internal/channelz"
|
||||||
|
icredentials "google.golang.org/grpc/internal/credentials"
|
||||||
|
"google.golang.org/grpc/internal/grpcutil"
|
||||||
|
imetadata "google.golang.org/grpc/internal/metadata"
|
||||||
"google.golang.org/grpc/internal/syscall"
|
"google.golang.org/grpc/internal/syscall"
|
||||||
|
"google.golang.org/grpc/internal/transport/networktype"
|
||||||
"google.golang.org/grpc/keepalive"
|
"google.golang.org/grpc/keepalive"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
|
|
@ -59,7 +60,7 @@ type http2Client struct {
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
ctxDone <-chan struct{} // Cache the ctx.Done() chan.
|
ctxDone <-chan struct{} // Cache the ctx.Done() chan.
|
||||||
userAgent string
|
userAgent string
|
||||||
md interface{}
|
md metadata.MD
|
||||||
conn net.Conn // underlying communication channel
|
conn net.Conn // underlying communication channel
|
||||||
loopy *loopyWriter
|
loopy *loopyWriter
|
||||||
remoteAddr net.Addr
|
remoteAddr net.Addr
|
||||||
|
|
@ -114,6 +115,9 @@ type http2Client struct {
|
||||||
// goAwayReason records the http2.ErrCode and debug data received with the
|
// goAwayReason records the http2.ErrCode and debug data received with the
|
||||||
// GoAway frame.
|
// GoAway frame.
|
||||||
goAwayReason GoAwayReason
|
goAwayReason GoAwayReason
|
||||||
|
// goAwayDebugMessage contains a detailed human readable string about a
|
||||||
|
// GoAway frame, useful for error messages.
|
||||||
|
goAwayDebugMessage string
|
||||||
// A condition variable used to signal when the keepalive goroutine should
|
// A condition variable used to signal when the keepalive goroutine should
|
||||||
// go dormant. The condition for dormancy is based on the number of active
|
// go dormant. The condition for dormancy is based on the number of active
|
||||||
// streams and the `PermitWithoutStream` keepalive client parameter. And
|
// streams and the `PermitWithoutStream` keepalive client parameter. And
|
||||||
|
|
@ -137,11 +141,27 @@ type http2Client struct {
|
||||||
connectionID uint64
|
connectionID uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr string) (net.Conn, error) {
|
func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr resolver.Address, useProxy bool, grpcUA string) (net.Conn, error) {
|
||||||
|
address := addr.Addr
|
||||||
|
networkType, ok := networktype.Get(addr)
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
return fn(ctx, addr)
|
if networkType == "unix" && !strings.HasPrefix(address, "\x00") {
|
||||||
|
// For backward compatibility, if the user dialed "unix:///path",
|
||||||
|
// the passthrough resolver would be used and the user's custom
|
||||||
|
// dialer would see "unix:///path". Since the unix resolver is used
|
||||||
|
// and the address is now "/path", prepend "unix://" so the user's
|
||||||
|
// custom dialer sees the same address.
|
||||||
|
return fn(ctx, "unix://"+address)
|
||||||
}
|
}
|
||||||
return (&net.Dialer{}).DialContext(ctx, "tcp", addr)
|
return fn(ctx, address)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
networkType, address = parseDialTarget(address)
|
||||||
|
}
|
||||||
|
if networkType == "tcp" && useProxy {
|
||||||
|
return proxyDial(ctx, address, grpcUA)
|
||||||
|
}
|
||||||
|
return (&net.Dialer{}).DialContext(ctx, networkType, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isTemporary(err error) bool {
|
func isTemporary(err error) bool {
|
||||||
|
|
@ -172,7 +192,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
conn, err := dial(connectCtx, opts.Dialer, addr.Addr)
|
conn, err := dial(connectCtx, opts.Dialer, addr, opts.UseProxy, opts.UserAgent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if opts.FailOnNonTempDialError {
|
if opts.FailOnNonTempDialError {
|
||||||
return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err)
|
return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err)
|
||||||
|
|
@ -220,12 +240,23 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||||
// Attributes field of resolver.Address, which is shoved into connectCtx
|
// Attributes field of resolver.Address, which is shoved into connectCtx
|
||||||
// and passed to the credential handshaker. This makes it possible for
|
// and passed to the credential handshaker. This makes it possible for
|
||||||
// address specific arbitrary data to reach the credential handshaker.
|
// address specific arbitrary data to reach the credential handshaker.
|
||||||
contextWithHandshakeInfo := internal.NewClientHandshakeInfoContext.(func(context.Context, credentials.ClientHandshakeInfo) context.Context)
|
connectCtx = icredentials.NewClientHandshakeInfoContext(connectCtx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes})
|
||||||
connectCtx = contextWithHandshakeInfo(connectCtx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes})
|
|
||||||
conn, authInfo, err = transportCreds.ClientHandshake(connectCtx, addr.ServerName, conn)
|
conn, authInfo, err = transportCreds.ClientHandshake(connectCtx, addr.ServerName, conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, connectionErrorf(isTemporary(err), err, "transport: authentication handshake failed: %v", err)
|
return nil, connectionErrorf(isTemporary(err), err, "transport: authentication handshake failed: %v", err)
|
||||||
}
|
}
|
||||||
|
for _, cd := range perRPCCreds {
|
||||||
|
if cd.RequireTransportSecurity() {
|
||||||
|
if ci, ok := authInfo.(interface {
|
||||||
|
GetCommonAuthInfo() credentials.CommonAuthInfo
|
||||||
|
}); ok {
|
||||||
|
secLevel := ci.GetCommonAuthInfo().SecurityLevel
|
||||||
|
if secLevel != credentials.InvalidSecurityLevel && secLevel < credentials.PrivacyAndIntegrity {
|
||||||
|
return nil, connectionErrorf(true, nil, "transport: cannot send secure credentials on an insecure connection")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
isSecure = true
|
isSecure = true
|
||||||
if transportCreds.Info().SecurityProtocol == "tls" {
|
if transportCreds.Info().SecurityProtocol == "tls" {
|
||||||
scheme = "https"
|
scheme = "https"
|
||||||
|
|
@ -248,7 +279,6 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||||
ctxDone: ctx.Done(), // Cache Done chan.
|
ctxDone: ctx.Done(), // Cache Done chan.
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
userAgent: opts.UserAgent,
|
userAgent: opts.UserAgent,
|
||||||
md: addr.Metadata,
|
|
||||||
conn: conn,
|
conn: conn,
|
||||||
remoteAddr: conn.RemoteAddr(),
|
remoteAddr: conn.RemoteAddr(),
|
||||||
localAddr: conn.LocalAddr(),
|
localAddr: conn.LocalAddr(),
|
||||||
|
|
@ -276,6 +306,12 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||||
keepaliveEnabled: keepaliveEnabled,
|
keepaliveEnabled: keepaliveEnabled,
|
||||||
bufferPool: newBufferPool(),
|
bufferPool: newBufferPool(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if md, ok := addr.Metadata.(*metadata.MD); ok {
|
||||||
|
t.md = *md
|
||||||
|
} else if md := imetadata.Get(addr); md != nil {
|
||||||
|
t.md = md
|
||||||
|
}
|
||||||
t.controlBuf = newControlBuffer(t.ctxDone)
|
t.controlBuf = newControlBuffer(t.ctxDone)
|
||||||
if opts.InitialWindowSize >= defaultWindowSize {
|
if opts.InitialWindowSize >= defaultWindowSize {
|
||||||
t.initialWindowSize = opts.InitialWindowSize
|
t.initialWindowSize = opts.InitialWindowSize
|
||||||
|
|
@ -312,12 +348,14 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||||
// Send connection preface to server.
|
// Send connection preface to server.
|
||||||
n, err := t.conn.Write(clientPreface)
|
n, err := t.conn.Write(clientPreface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Close()
|
err = connectionErrorf(true, err, "transport: failed to write client preface: %v", err)
|
||||||
return nil, connectionErrorf(true, err, "transport: failed to write client preface: %v", err)
|
t.Close(err)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
if n != len(clientPreface) {
|
if n != len(clientPreface) {
|
||||||
t.Close()
|
err = connectionErrorf(true, nil, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
|
||||||
return nil, connectionErrorf(true, err, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
|
t.Close(err)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
var ss []http2.Setting
|
var ss []http2.Setting
|
||||||
|
|
||||||
|
|
@ -335,14 +373,16 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
||||||
}
|
}
|
||||||
err = t.framer.fr.WriteSettings(ss...)
|
err = t.framer.fr.WriteSettings(ss...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Close()
|
err = connectionErrorf(true, err, "transport: failed to write initial settings frame: %v", err)
|
||||||
return nil, connectionErrorf(true, err, "transport: failed to write initial settings frame: %v", err)
|
t.Close(err)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
// Adjust the connection flow control window if needed.
|
// Adjust the connection flow control window if needed.
|
||||||
if delta := uint32(icwz - defaultWindowSize); delta > 0 {
|
if delta := uint32(icwz - defaultWindowSize); delta > 0 {
|
||||||
if err := t.framer.fr.WriteWindowUpdate(0, delta); err != nil {
|
if err := t.framer.fr.WriteWindowUpdate(0, delta); err != nil {
|
||||||
t.Close()
|
err = connectionErrorf(true, err, "transport: failed to write window update: %v", err)
|
||||||
return nil, connectionErrorf(true, err, "transport: failed to write window update: %v", err)
|
t.Close(err)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -379,6 +419,7 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
|
||||||
buf: newRecvBuffer(),
|
buf: newRecvBuffer(),
|
||||||
headerChan: make(chan struct{}),
|
headerChan: make(chan struct{}),
|
||||||
contentSubtype: callHdr.ContentSubtype,
|
contentSubtype: callHdr.ContentSubtype,
|
||||||
|
doneFunc: callHdr.DoneFunc,
|
||||||
}
|
}
|
||||||
s.wq = newWriteQuota(defaultWriteQuota, s.done)
|
s.wq = newWriteQuota(defaultWriteQuota, s.done)
|
||||||
s.requestRead = func(n int) {
|
s.requestRead = func(n int) {
|
||||||
|
|
@ -418,7 +459,7 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr)
|
||||||
Method: callHdr.Method,
|
Method: callHdr.Method,
|
||||||
AuthInfo: t.authInfo,
|
AuthInfo: t.authInfo,
|
||||||
}
|
}
|
||||||
ctxWithRequestInfo := internal.NewRequestInfoContext.(func(context.Context, credentials.RequestInfo) context.Context)(ctx, ri)
|
ctxWithRequestInfo := icredentials.NewRequestInfoContext(ctx, ri)
|
||||||
authData, err := t.getTrAuthData(ctxWithRequestInfo, aud)
|
authData, err := t.getTrAuthData(ctxWithRequestInfo, aud)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -481,19 +522,18 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr)
|
||||||
for _, vv := range added {
|
for _, vv := range added {
|
||||||
for i, v := range vv {
|
for i, v := range vv {
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
k = v
|
k = strings.ToLower(v)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
|
// HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
|
||||||
if isReservedHeader(k) {
|
if isReservedHeader(k) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
headerFields = append(headerFields, hpack.HeaderField{Name: strings.ToLower(k), Value: encodeMetadataHeader(k, v)})
|
headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if md, ok := t.md.(*metadata.MD); ok {
|
for k, vv := range t.md {
|
||||||
for k, vv := range *md {
|
|
||||||
if isReservedHeader(k) {
|
if isReservedHeader(k) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -501,7 +541,6 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr)
|
||||||
headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
|
headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return headerFields, nil
|
return headerFields, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -549,9 +588,12 @@ func (t *http2Client) getCallAuthData(ctx context.Context, audience string, call
|
||||||
// Note: if these credentials are provided both via dial options and call
|
// Note: if these credentials are provided both via dial options and call
|
||||||
// options, then both sets of credentials will be applied.
|
// options, then both sets of credentials will be applied.
|
||||||
if callCreds := callHdr.Creds; callCreds != nil {
|
if callCreds := callHdr.Creds; callCreds != nil {
|
||||||
if !t.isSecure && callCreds.RequireTransportSecurity() {
|
if callCreds.RequireTransportSecurity() {
|
||||||
|
ri, _ := credentials.RequestInfoFromContext(ctx)
|
||||||
|
if !t.isSecure || credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity) != nil {
|
||||||
return nil, status.Error(codes.Unauthenticated, "transport: cannot send secure credentials on an insecure connection")
|
return nil, status.Error(codes.Unauthenticated, "transport: cannot send secure credentials on an insecure connection")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
data, err := callCreds.GetRequestMetadata(ctx, audience)
|
data, err := callCreds.GetRequestMetadata(ctx, audience)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "transport: %v", err)
|
return nil, status.Errorf(codes.Internal, "transport: %v", err)
|
||||||
|
|
@ -796,6 +838,9 @@ func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2.
|
||||||
t.controlBuf.executeAndPut(addBackStreamQuota, cleanup)
|
t.controlBuf.executeAndPut(addBackStreamQuota, cleanup)
|
||||||
// This will unblock write.
|
// This will unblock write.
|
||||||
close(s.done)
|
close(s.done)
|
||||||
|
if s.doneFunc != nil {
|
||||||
|
s.doneFunc()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close kicks off the shutdown process of the transport. This should be called
|
// Close kicks off the shutdown process of the transport. This should be called
|
||||||
|
|
@ -805,12 +850,12 @@ func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2.
|
||||||
// This method blocks until the addrConn that initiated this transport is
|
// This method blocks until the addrConn that initiated this transport is
|
||||||
// re-connected. This happens because t.onClose() begins reconnect logic at the
|
// re-connected. This happens because t.onClose() begins reconnect logic at the
|
||||||
// addrConn level and blocks until the addrConn is successfully connected.
|
// addrConn level and blocks until the addrConn is successfully connected.
|
||||||
func (t *http2Client) Close() error {
|
func (t *http2Client) Close(err error) {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
// Make sure we only Close once.
|
// Make sure we only Close once.
|
||||||
if t.state == closing {
|
if t.state == closing {
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
// Call t.onClose before setting the state to closing to prevent the client
|
// Call t.onClose before setting the state to closing to prevent the client
|
||||||
// from attempting to create new streams ASAP.
|
// from attempting to create new streams ASAP.
|
||||||
|
|
@ -826,13 +871,19 @@ func (t *http2Client) Close() error {
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
t.controlBuf.finish()
|
t.controlBuf.finish()
|
||||||
t.cancel()
|
t.cancel()
|
||||||
err := t.conn.Close()
|
t.conn.Close()
|
||||||
if channelz.IsOn() {
|
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
|
||||||
|
// for understanding the root cause for this connection to be closed.
|
||||||
|
_, goAwayDebugMessage := t.GetGoAwayReason()
|
||||||
|
if len(goAwayDebugMessage) > 0 {
|
||||||
|
err = fmt.Errorf("closing transport due to: %v, received prior goaway: %v", err, goAwayDebugMessage)
|
||||||
|
}
|
||||||
// Notify all active streams.
|
// Notify all active streams.
|
||||||
for _, s := range streams {
|
for _, s := range streams {
|
||||||
t.closeStream(s, ErrConnClosing, false, http2.ErrCodeNo, status.New(codes.Unavailable, ErrConnClosing.Desc), nil, false)
|
t.closeStream(s, err, false, http2.ErrCodeNo, status.New(codes.Unavailable, err.Error()), nil, false)
|
||||||
}
|
}
|
||||||
if t.statsHandler != nil {
|
if t.statsHandler != nil {
|
||||||
connEnd := &stats.ConnEnd{
|
connEnd := &stats.ConnEnd{
|
||||||
|
|
@ -840,7 +891,6 @@ func (t *http2Client) Close() error {
|
||||||
}
|
}
|
||||||
t.statsHandler.HandleConn(t.ctx, connEnd)
|
t.statsHandler.HandleConn(t.ctx, connEnd)
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GracefulClose sets the state to draining, which prevents new streams from
|
// GracefulClose sets the state to draining, which prevents new streams from
|
||||||
|
|
@ -859,7 +909,7 @@ func (t *http2Client) GracefulClose() {
|
||||||
active := len(t.activeStreams)
|
active := len(t.activeStreams)
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
if active == 0 {
|
if active == 0 {
|
||||||
t.Close()
|
t.Close(ErrConnClosing)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.controlBuf.put(&incomingGoAway{})
|
t.controlBuf.put(&incomingGoAway{})
|
||||||
|
|
@ -1105,9 +1155,9 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
id := f.LastStreamID
|
id := f.LastStreamID
|
||||||
if id > 0 && id%2 != 1 {
|
if id > 0 && id%2 == 0 {
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
t.Close()
|
t.Close(connectionErrorf(true, nil, "received goaway with non-zero even-numbered numbered stream id: %v", id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// A client can receive multiple GoAways from the server (see
|
// A client can receive multiple GoAways from the server (see
|
||||||
|
|
@ -1125,7 +1175,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
|
||||||
// If there are multiple GoAways the first one should always have an ID greater than the following ones.
|
// If there are multiple GoAways the first one should always have an ID greater than the following ones.
|
||||||
if id > t.prevGoAwayID {
|
if id > t.prevGoAwayID {
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
t.Close()
|
t.Close(connectionErrorf(true, nil, "received goaway with stream id: %v, which exceeds stream id of previous goaway: %v", id, t.prevGoAwayID))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -1155,7 +1205,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
|
||||||
active := len(t.activeStreams)
|
active := len(t.activeStreams)
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
if active == 0 {
|
if active == 0 {
|
||||||
t.Close()
|
t.Close(connectionErrorf(true, nil, "received goaway and there are no active streams"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1171,12 +1221,13 @@ func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) {
|
||||||
t.goAwayReason = GoAwayTooManyPings
|
t.goAwayReason = GoAwayTooManyPings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
t.goAwayDebugMessage = fmt.Sprintf("code: %s, debug data: %v", f.ErrCode, string(f.DebugData()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *http2Client) GetGoAwayReason() GoAwayReason {
|
func (t *http2Client) GetGoAwayReason() (GoAwayReason, string) {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
return t.goAwayReason
|
return t.goAwayReason, t.goAwayDebugMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) {
|
func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) {
|
||||||
|
|
@ -1273,7 +1324,8 @@ func (t *http2Client) reader() {
|
||||||
// Check the validity of server preface.
|
// Check the validity of server preface.
|
||||||
frame, err := t.framer.fr.ReadFrame()
|
frame, err := t.framer.fr.ReadFrame()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Close() // this kicks off resetTransport, so must be last before return
|
err = connectionErrorf(true, err, "error reading server preface: %v", err)
|
||||||
|
t.Close(err) // this kicks off resetTransport, so must be last before return
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.conn.SetReadDeadline(time.Time{}) // reset deadline once we get the settings frame (we didn't time out, yay!)
|
t.conn.SetReadDeadline(time.Time{}) // reset deadline once we get the settings frame (we didn't time out, yay!)
|
||||||
|
|
@ -1282,7 +1334,8 @@ func (t *http2Client) reader() {
|
||||||
}
|
}
|
||||||
sf, ok := frame.(*http2.SettingsFrame)
|
sf, ok := frame.(*http2.SettingsFrame)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Close() // this kicks off resetTransport, so must be last before return
|
// this kicks off resetTransport, so must be last before return
|
||||||
|
t.Close(connectionErrorf(true, nil, "initial http2 frame from server is not a settings frame: %T", frame))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.onPrefaceReceipt()
|
t.onPrefaceReceipt()
|
||||||
|
|
@ -1318,7 +1371,7 @@ func (t *http2Client) reader() {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
// Transport error.
|
// Transport error.
|
||||||
t.Close()
|
t.Close(connectionErrorf(true, err, "error reading from server: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1377,7 +1430,7 @@ func (t *http2Client) keepalive() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if outstandingPing && timeoutLeft <= 0 {
|
if outstandingPing && timeoutLeft <= 0 {
|
||||||
t.Close()
|
t.Close(connectionErrorf(true, nil, "keepalive ping failed to receive ACK within timeout"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
@ -355,26 +356,6 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||||
if state.data.statsTrace != nil {
|
if state.data.statsTrace != nil {
|
||||||
s.ctx = stats.SetIncomingTrace(s.ctx, state.data.statsTrace)
|
s.ctx = stats.SetIncomingTrace(s.ctx, state.data.statsTrace)
|
||||||
}
|
}
|
||||||
if t.inTapHandle != nil {
|
|
||||||
var err error
|
|
||||||
info := &tap.Info{
|
|
||||||
FullMethodName: state.data.method,
|
|
||||||
}
|
|
||||||
s.ctx, err = t.inTapHandle(s.ctx, info)
|
|
||||||
if err != nil {
|
|
||||||
if logger.V(logLevel) {
|
|
||||||
logger.Warningf("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err)
|
|
||||||
}
|
|
||||||
t.controlBuf.put(&cleanupStream{
|
|
||||||
streamID: s.id,
|
|
||||||
rst: true,
|
|
||||||
rstCode: http2.ErrCodeRefusedStream,
|
|
||||||
onWrite: func() {},
|
|
||||||
})
|
|
||||||
s.cancel()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
if t.state != reachable {
|
if t.state != reachable {
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
|
|
@ -402,6 +383,39 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
t.maxStreamID = streamID
|
t.maxStreamID = streamID
|
||||||
|
if state.data.httpMethod != http.MethodPost {
|
||||||
|
t.mu.Unlock()
|
||||||
|
if logger.V(logLevel) {
|
||||||
|
logger.Warningf("transport: http2Server.operateHeaders parsed a :method field: %v which should be POST", state.data.httpMethod)
|
||||||
|
}
|
||||||
|
t.controlBuf.put(&cleanupStream{
|
||||||
|
streamID: streamID,
|
||||||
|
rst: true,
|
||||||
|
rstCode: http2.ErrCodeProtocol,
|
||||||
|
onWrite: func() {},
|
||||||
|
})
|
||||||
|
s.cancel()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t.inTapHandle != nil {
|
||||||
|
var err error
|
||||||
|
if s.ctx, err = t.inTapHandle(s.ctx, &tap.Info{FullMethodName: state.data.method}); err != nil {
|
||||||
|
t.mu.Unlock()
|
||||||
|
if logger.V(logLevel) {
|
||||||
|
logger.Infof("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err)
|
||||||
|
}
|
||||||
|
stat, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
stat = status.New(codes.PermissionDenied, err.Error())
|
||||||
|
}
|
||||||
|
t.controlBuf.put(&earlyAbortStream{
|
||||||
|
streamID: s.id,
|
||||||
|
contentSubtype: s.contentSubtype,
|
||||||
|
status: stat,
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
t.activeStreams[streamID] = s
|
t.activeStreams[streamID] = s
|
||||||
if len(t.activeStreams) == 1 {
|
if len(t.activeStreams) == 1 {
|
||||||
t.idle = time.Time{}
|
t.idle = time.Time{}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -110,6 +111,7 @@ type parsedHeaderData struct {
|
||||||
timeoutSet bool
|
timeoutSet bool
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
method string
|
method string
|
||||||
|
httpMethod string
|
||||||
// key-value metadata map from the peer.
|
// key-value metadata map from the peer.
|
||||||
mdata map[string][]string
|
mdata map[string][]string
|
||||||
statsTags []byte
|
statsTags []byte
|
||||||
|
|
@ -362,6 +364,8 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) {
|
||||||
}
|
}
|
||||||
d.data.statsTrace = v
|
d.data.statsTrace = v
|
||||||
d.addMetadata(f.Name, string(v))
|
d.addMetadata(f.Name, string(v))
|
||||||
|
case ":method":
|
||||||
|
d.data.httpMethod = f.Value
|
||||||
default:
|
default:
|
||||||
if isReservedHeader(f.Name) && !isWhitelistedHeader(f.Name) {
|
if isReservedHeader(f.Name) && !isWhitelistedHeader(f.Name) {
|
||||||
break
|
break
|
||||||
|
|
@ -598,3 +602,31 @@ func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderList
|
||||||
f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
|
f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseDialTarget returns the network and address to pass to dialer.
|
||||||
|
func parseDialTarget(target string) (string, string) {
|
||||||
|
net := "tcp"
|
||||||
|
m1 := strings.Index(target, ":")
|
||||||
|
m2 := strings.Index(target, ":/")
|
||||||
|
// handle unix:addr which will fail with url.Parse
|
||||||
|
if m1 >= 0 && m2 < 0 {
|
||||||
|
if n := target[0:m1]; n == "unix" {
|
||||||
|
return n, target[m1+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if m2 >= 0 {
|
||||||
|
t, err := url.Parse(target)
|
||||||
|
if err != nil {
|
||||||
|
return net, target
|
||||||
|
}
|
||||||
|
scheme := t.Scheme
|
||||||
|
addr := t.Path
|
||||||
|
if scheme == "unix" {
|
||||||
|
if addr == "" {
|
||||||
|
addr = t.Host
|
||||||
|
}
|
||||||
|
return scheme, addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return net, target
|
||||||
|
}
|
||||||
|
|
|
||||||
46
vendor/google.golang.org/grpc/internal/transport/networktype/networktype.go
generated
vendored
Normal file
46
vendor/google.golang.org/grpc/internal/transport/networktype/networktype.go
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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 networktype declares the network type to be used in the default
|
||||||
|
// dailer. Attribute of a resolver.Address.
|
||||||
|
package networktype
|
||||||
|
|
||||||
|
import (
|
||||||
|
"google.golang.org/grpc/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
// keyType is the key to use for storing State in Attributes.
|
||||||
|
type keyType string
|
||||||
|
|
||||||
|
const key = keyType("grpc.internal.transport.networktype")
|
||||||
|
|
||||||
|
// Set returns a copy of the provided address with attributes containing networkType.
|
||||||
|
func Set(address resolver.Address, networkType string) resolver.Address {
|
||||||
|
address.Attributes = address.Attributes.WithValues(key, networkType)
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the network type in the resolver.Address and true, or "", false
|
||||||
|
// if not present.
|
||||||
|
func Get(address resolver.Address) (string, bool) {
|
||||||
|
v := address.Attributes.Value(key)
|
||||||
|
if v == nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return v.(string), true
|
||||||
|
}
|
||||||
|
|
@ -16,13 +16,12 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package grpc
|
package transport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
@ -34,8 +33,6 @@ import (
|
||||||
const proxyAuthHeaderKey = "Proxy-Authorization"
|
const proxyAuthHeaderKey = "Proxy-Authorization"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// errDisabled indicates that proxy is disabled for the address.
|
|
||||||
errDisabled = errors.New("proxy is disabled for the address")
|
|
||||||
// The following variable will be overwritten in the tests.
|
// The following variable will be overwritten in the tests.
|
||||||
httpProxyFromEnvironment = http.ProxyFromEnvironment
|
httpProxyFromEnvironment = http.ProxyFromEnvironment
|
||||||
)
|
)
|
||||||
|
|
@ -51,9 +48,6 @@ func mapAddress(ctx context.Context, address string) (*url.URL, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if url == nil {
|
|
||||||
return nil, errDisabled
|
|
||||||
}
|
|
||||||
return url, nil
|
return url, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +70,7 @@ func basicAuth(username, password string) string {
|
||||||
return base64.StdEncoding.EncodeToString([]byte(auth))
|
return base64.StdEncoding.EncodeToString([]byte(auth))
|
||||||
}
|
}
|
||||||
|
|
||||||
func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr string, proxyURL *url.URL) (_ net.Conn, err error) {
|
func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr string, proxyURL *url.URL, grpcUA string) (_ net.Conn, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
|
|
@ -115,33 +109,29 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr stri
|
||||||
return &bufConn{Conn: conn, r: r}, nil
|
return &bufConn{Conn: conn, r: r}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// newProxyDialer returns a dialer that connects to proxy first if necessary.
|
// proxyDial dials, connecting to a proxy first if necessary. Checks if a proxy
|
||||||
// The returned dialer checks if a proxy is necessary, dial to the proxy with the
|
// is necessary, dials, does the HTTP CONNECT handshake, and returns the
|
||||||
// provided dialer, does HTTP CONNECT handshake and returns the connection.
|
// connection.
|
||||||
func newProxyDialer(dialer func(context.Context, string) (net.Conn, error)) func(context.Context, string) (net.Conn, error) {
|
func proxyDial(ctx context.Context, addr string, grpcUA string) (conn net.Conn, err error) {
|
||||||
return func(ctx context.Context, addr string) (conn net.Conn, err error) {
|
newAddr := addr
|
||||||
var newAddr string
|
|
||||||
proxyURL, err := mapAddress(ctx, addr)
|
proxyURL, err := mapAddress(ctx, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != errDisabled {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
newAddr = addr
|
if proxyURL != nil {
|
||||||
} else {
|
|
||||||
newAddr = proxyURL.Host
|
newAddr = proxyURL.Host
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err = dialer(ctx, newAddr)
|
conn, err = (&net.Dialer{}).DialContext(ctx, "tcp", newAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if proxyURL != nil {
|
if proxyURL != nil {
|
||||||
// proxy is disabled if proxyURL is nil.
|
// proxy is disabled if proxyURL is nil.
|
||||||
conn, err = doHTTPConnectHandshake(ctx, conn, addr, proxyURL)
|
conn, err = doHTTPConnectHandshake(ctx, conn, addr, proxyURL, grpcUA)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
|
func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
@ -241,6 +241,7 @@ type Stream struct {
|
||||||
ctx context.Context // the associated context of the stream
|
ctx context.Context // the associated context of the stream
|
||||||
cancel context.CancelFunc // always nil for client side Stream
|
cancel context.CancelFunc // always nil for client side Stream
|
||||||
done chan struct{} // closed at the end of stream to unblock writers. On the client side.
|
done chan struct{} // closed at the end of stream to unblock writers. On the client side.
|
||||||
|
doneFunc func() // invoked at the end of stream on client side.
|
||||||
ctxDone <-chan struct{} // same as done chan but for server side. Cache of ctx.Done() (for performance)
|
ctxDone <-chan struct{} // same as done chan but for server side. Cache of ctx.Done() (for performance)
|
||||||
method string // the associated RPC method of the stream
|
method string // the associated RPC method of the stream
|
||||||
recvCompress string
|
recvCompress string
|
||||||
|
|
@ -569,6 +570,8 @@ type ConnectOptions struct {
|
||||||
ChannelzParentID int64
|
ChannelzParentID int64
|
||||||
// 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 bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClientTransport establishes the transport with the required ConnectOptions
|
// NewClientTransport establishes the transport with the required ConnectOptions
|
||||||
|
|
@ -609,6 +612,8 @@ type CallHdr struct {
|
||||||
ContentSubtype string
|
ContentSubtype string
|
||||||
|
|
||||||
PreviousAttempts int // value of grpc-previous-rpc-attempts header to set
|
PreviousAttempts int // value of grpc-previous-rpc-attempts header to set
|
||||||
|
|
||||||
|
DoneFunc func() // called when the stream is finished
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientTransport is the common interface for all gRPC client-side transport
|
// ClientTransport is the common interface for all gRPC client-side transport
|
||||||
|
|
@ -617,7 +622,7 @@ type ClientTransport interface {
|
||||||
// Close tears down this transport. Once it returns, the transport
|
// Close tears down this transport. Once it returns, the transport
|
||||||
// should not be accessed any more. The caller must make sure this
|
// should not be accessed any more. The caller must make sure this
|
||||||
// is called only once.
|
// is called only once.
|
||||||
Close() error
|
Close(err error)
|
||||||
|
|
||||||
// GracefulClose starts to tear down the transport: the transport will stop
|
// GracefulClose starts to tear down the transport: the transport will stop
|
||||||
// accepting new RPCs and NewStream will return error. Once all streams are
|
// accepting new RPCs and NewStream will return error. Once all streams are
|
||||||
|
|
@ -651,8 +656,9 @@ type ClientTransport interface {
|
||||||
// HTTP/2).
|
// HTTP/2).
|
||||||
GoAway() <-chan struct{}
|
GoAway() <-chan struct{}
|
||||||
|
|
||||||
// GetGoAwayReason returns the reason why GoAway frame was received.
|
// GetGoAwayReason returns the reason why GoAway frame was received, along
|
||||||
GetGoAwayReason() GoAwayReason
|
// with a human readable string with debug info.
|
||||||
|
GetGoAwayReason() (GoAwayReason, string)
|
||||||
|
|
||||||
// RemoteAddr returns the remote network address.
|
// RemoteAddr returns the remote network address.
|
||||||
RemoteAddr() net.Addr
|
RemoteAddr() net.Addr
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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 internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"google.golang.org/grpc/attributes"
|
||||||
|
"google.golang.org/grpc/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
// handshakeClusterNameKey is the type used as the key to store cluster name in
|
||||||
|
// the Attributes field of resolver.Address.
|
||||||
|
type handshakeClusterNameKey struct{}
|
||||||
|
|
||||||
|
// SetXDSHandshakeClusterName returns a copy of addr in which the Attributes field
|
||||||
|
// is updated with the cluster name.
|
||||||
|
func SetXDSHandshakeClusterName(addr resolver.Address, clusterName string) resolver.Address {
|
||||||
|
addr.Attributes = addr.Attributes.WithValues(handshakeClusterNameKey{}, clusterName)
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetXDSHandshakeClusterName returns cluster name stored in attr.
|
||||||
|
func GetXDSHandshakeClusterName(attr *attributes.Attributes) (string, bool) {
|
||||||
|
v := attr.Value(handshakeClusterNameKey{})
|
||||||
|
name, ok := v.(string)
|
||||||
|
return name, ok
|
||||||
|
}
|
||||||
|
|
@ -75,13 +75,9 @@ func Pairs(kv ...string) MD {
|
||||||
panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
|
panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
|
||||||
}
|
}
|
||||||
md := MD{}
|
md := MD{}
|
||||||
var key string
|
for i := 0; i < len(kv); i += 2 {
|
||||||
for i, s := range kv {
|
key := strings.ToLower(kv[i])
|
||||||
if i%2 == 0 {
|
md[key] = append(md[key], kv[i+1])
|
||||||
key = strings.ToLower(s)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
md[key] = append(md[key], s)
|
|
||||||
}
|
}
|
||||||
return md
|
return md
|
||||||
}
|
}
|
||||||
|
|
@ -195,12 +191,18 @@ func FromOutgoingContext(ctx context.Context) (MD, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
mds := make([]MD, 0, len(raw.added)+1)
|
out := raw.md.Copy()
|
||||||
mds = append(mds, raw.md)
|
for _, added := range raw.added {
|
||||||
for _, vv := range raw.added {
|
if len(added)%2 == 1 {
|
||||||
mds = append(mds, Pairs(vv...))
|
panic(fmt.Sprintf("metadata: FromOutgoingContext got an odd number of input pairs for metadata: %d", len(added)))
|
||||||
}
|
}
|
||||||
return Join(mds...), ok
|
|
||||||
|
for i := 0; i < len(added); i += 2 {
|
||||||
|
key := strings.ToLower(added[i])
|
||||||
|
out[key] = append(out[key], added[i+1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
type rawMD struct {
|
type rawMD struct {
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ func (b *pickfirstBalancer) UpdateClientConnState(cs balancer.ClientConnState) e
|
||||||
b.cc.UpdateState(balancer.State{ConnectivityState: connectivity.Idle, Picker: &picker{result: balancer.PickResult{SubConn: b.sc}}})
|
b.cc.UpdateState(balancer.State{ConnectivityState: connectivity.Idle, Picker: &picker{result: balancer.PickResult{SubConn: b.sc}}})
|
||||||
b.sc.Connect()
|
b.sc.Connect()
|
||||||
} else {
|
} else {
|
||||||
b.sc.UpdateAddresses(cs.ResolverState.Addresses)
|
b.cc.UpdateAddresses(b.sc, cs.ResolverState.Addresses)
|
||||||
b.sc.Connect()
|
b.sc.Connect()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -40,29 +40,14 @@ echo "go install cmd/protoc-gen-go-grpc"
|
||||||
echo "git clone https://github.com/grpc/grpc-proto"
|
echo "git clone https://github.com/grpc/grpc-proto"
|
||||||
git clone --quiet https://github.com/grpc/grpc-proto ${WORKDIR}/grpc-proto
|
git clone --quiet https://github.com/grpc/grpc-proto ${WORKDIR}/grpc-proto
|
||||||
|
|
||||||
|
echo "git clone https://github.com/protocolbuffers/protobuf"
|
||||||
|
git clone --quiet https://github.com/protocolbuffers/protobuf ${WORKDIR}/protobuf
|
||||||
|
|
||||||
# Pull in code.proto as a proto dependency
|
# Pull in code.proto as a proto dependency
|
||||||
mkdir -p ${WORKDIR}/googleapis/google/rpc
|
mkdir -p ${WORKDIR}/googleapis/google/rpc
|
||||||
echo "curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto"
|
echo "curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto"
|
||||||
curl --silent https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto > ${WORKDIR}/googleapis/google/rpc/code.proto
|
curl --silent https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto > ${WORKDIR}/googleapis/google/rpc/code.proto
|
||||||
|
|
||||||
# Pull in the following repos to build the MeshCA config proto.
|
|
||||||
ENVOY_API_REPOS=(
|
|
||||||
"https://github.com/envoyproxy/data-plane-api"
|
|
||||||
"https://github.com/cncf/udpa"
|
|
||||||
"https://github.com/envoyproxy/protoc-gen-validate"
|
|
||||||
)
|
|
||||||
for repo in ${ENVOY_API_REPOS[@]}; do
|
|
||||||
dirname=$(basename ${repo})
|
|
||||||
mkdir -p ${WORKDIR}/${dirname}
|
|
||||||
echo "git clone ${repo}"
|
|
||||||
git clone --quiet ${repo} ${WORKDIR}/${dirname}
|
|
||||||
done
|
|
||||||
|
|
||||||
# Pull in the MeshCA service proto.
|
|
||||||
mkdir -p ${WORKDIR}/istio/istio/google/security/meshca/v1
|
|
||||||
echo "curl https://raw.githubusercontent.com/istio/istio/master/security/proto/providers/google/meshca.proto"
|
|
||||||
curl --silent https://raw.githubusercontent.com/istio/istio/master/security/proto/providers/google/meshca.proto > ${WORKDIR}/istio/istio/google/security/meshca/v1/meshca.proto
|
|
||||||
|
|
||||||
mkdir -p ${WORKDIR}/out
|
mkdir -p ${WORKDIR}/out
|
||||||
|
|
||||||
# Generates sources without the embed requirement
|
# Generates sources without the embed requirement
|
||||||
|
|
@ -84,15 +69,14 @@ SOURCES=(
|
||||||
${WORKDIR}/grpc-proto/grpc/lookup/v1/rls.proto
|
${WORKDIR}/grpc-proto/grpc/lookup/v1/rls.proto
|
||||||
${WORKDIR}/grpc-proto/grpc/lookup/v1/rls_config.proto
|
${WORKDIR}/grpc-proto/grpc/lookup/v1/rls_config.proto
|
||||||
${WORKDIR}/grpc-proto/grpc/service_config/service_config.proto
|
${WORKDIR}/grpc-proto/grpc/service_config/service_config.proto
|
||||||
${WORKDIR}/grpc-proto/grpc/tls/provider/meshca/experimental/config.proto
|
${WORKDIR}/grpc-proto/grpc/testing/*.proto
|
||||||
${WORKDIR}/istio/istio/google/security/meshca/v1/meshca.proto
|
${WORKDIR}/grpc-proto/grpc/core/*.proto
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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,\
|
OPTS=Mgrpc/service_config/service_config.proto=/internal/proto/grpc_service_config,Mgrpc/core/stats.proto=google.golang.org/grpc/interop/grpc_testing/core
|
||||||
Menvoy/config/core/v3/config_source.proto=github.com/envoyproxy/go-control-plane/envoy/config/core/v3
|
|
||||||
|
|
||||||
for src in ${SOURCES[@]}; do
|
for src in ${SOURCES[@]}; do
|
||||||
echo "protoc ${src}"
|
echo "protoc ${src}"
|
||||||
|
|
@ -100,9 +84,7 @@ for src in ${SOURCES[@]}; do
|
||||||
-I"." \
|
-I"." \
|
||||||
-I${WORKDIR}/grpc-proto \
|
-I${WORKDIR}/grpc-proto \
|
||||||
-I${WORKDIR}/googleapis \
|
-I${WORKDIR}/googleapis \
|
||||||
-I${WORKDIR}/data-plane-api \
|
-I${WORKDIR}/protobuf/src \
|
||||||
-I${WORKDIR}/udpa \
|
|
||||||
-I${WORKDIR}/protoc-gen-validate \
|
|
||||||
-I${WORKDIR}/istio \
|
-I${WORKDIR}/istio \
|
||||||
${src}
|
${src}
|
||||||
done
|
done
|
||||||
|
|
@ -113,9 +95,7 @@ for src in ${LEGACY_SOURCES[@]}; do
|
||||||
-I"." \
|
-I"." \
|
||||||
-I${WORKDIR}/grpc-proto \
|
-I${WORKDIR}/grpc-proto \
|
||||||
-I${WORKDIR}/googleapis \
|
-I${WORKDIR}/googleapis \
|
||||||
-I${WORKDIR}/data-plane-api \
|
-I${WORKDIR}/protobuf/src \
|
||||||
-I${WORKDIR}/udpa \
|
|
||||||
-I${WORKDIR}/protoc-gen-validate \
|
|
||||||
-I${WORKDIR}/istio \
|
-I${WORKDIR}/istio \
|
||||||
${src}
|
${src}
|
||||||
done
|
done
|
||||||
|
|
@ -132,8 +112,8 @@ rm ${WORKDIR}/out/google.golang.org/grpc/reflection/grpc_testingv3/*.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
|
||||||
|
|
||||||
# istio/google/security/meshca/v1/meshca.proto does not have a go_package option.
|
# grpc/testing does not have a go_package option.
|
||||||
mkdir -p ${WORKDIR}/out/google.golang.org/grpc/credentials/tls/certprovider/meshca/internal/v1/
|
mv ${WORKDIR}/out/grpc/testing/*.pb.go interop/grpc_testing/
|
||||||
mv ${WORKDIR}/out/istio/google/security/meshca/v1/* ${WORKDIR}/out/google.golang.org/grpc/credentials/tls/certprovider/meshca/internal/v1/
|
mv ${WORKDIR}/out/grpc/core/*.pb.go interop/grpc_testing/core/
|
||||||
|
|
||||||
cp -R ${WORKDIR}/out/google.golang.org/grpc/* .
|
cp -R ${WORKDIR}/out/google.golang.org/grpc/* .
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ type State struct {
|
||||||
// gRPC to add new methods to this interface.
|
// gRPC to add new methods to this interface.
|
||||||
type ClientConn interface {
|
type ClientConn interface {
|
||||||
// UpdateState updates the state of the ClientConn appropriately.
|
// UpdateState updates the state of the ClientConn appropriately.
|
||||||
UpdateState(State)
|
UpdateState(State) error
|
||||||
// ReportError notifies the ClientConn that the Resolver encountered an
|
// ReportError notifies the ClientConn that the Resolver encountered an
|
||||||
// error. The ClientConn will notify the load balancer and begin calling
|
// error. The ClientConn will notify the load balancer and begin calling
|
||||||
// ResolveNow on the Resolver with exponential backoff.
|
// ResolveNow on the Resolver with exponential backoff.
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"google.golang.org/grpc/balancer"
|
"google.golang.org/grpc/balancer"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
|
@ -40,9 +39,6 @@ type ccResolverWrapper struct {
|
||||||
resolver resolver.Resolver
|
resolver resolver.Resolver
|
||||||
done *grpcsync.Event
|
done *grpcsync.Event
|
||||||
curState resolver.State
|
curState resolver.State
|
||||||
|
|
||||||
pollingMu sync.Mutex
|
|
||||||
polling chan struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCCResolverWrapper uses the resolver.Builder to build a Resolver and
|
// newCCResolverWrapper uses the resolver.Builder to build a Resolver and
|
||||||
|
|
@ -93,59 +89,19 @@ func (ccr *ccResolverWrapper) close() {
|
||||||
ccr.resolverMu.Unlock()
|
ccr.resolverMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// poll begins or ends asynchronous polling of the resolver based on whether
|
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
|
||||||
// err is ErrBadResolverState.
|
|
||||||
func (ccr *ccResolverWrapper) poll(err error) {
|
|
||||||
ccr.pollingMu.Lock()
|
|
||||||
defer ccr.pollingMu.Unlock()
|
|
||||||
if err != balancer.ErrBadResolverState {
|
|
||||||
// stop polling
|
|
||||||
if ccr.polling != nil {
|
|
||||||
close(ccr.polling)
|
|
||||||
ccr.polling = nil
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ccr.polling != nil {
|
|
||||||
// already polling
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p := make(chan struct{})
|
|
||||||
ccr.polling = p
|
|
||||||
go func() {
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
ccr.resolveNow(resolver.ResolveNowOptions{})
|
|
||||||
t := time.NewTimer(ccr.cc.dopts.resolveNowBackoff(i))
|
|
||||||
select {
|
|
||||||
case <-p:
|
|
||||||
t.Stop()
|
|
||||||
return
|
|
||||||
case <-ccr.done.Done():
|
|
||||||
// Resolver has been closed.
|
|
||||||
t.Stop()
|
|
||||||
return
|
|
||||||
case <-t.C:
|
|
||||||
select {
|
|
||||||
case <-p:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
// Timer expired; re-resolve.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) {
|
|
||||||
if ccr.done.HasFired() {
|
if ccr.done.HasFired() {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: sending update to cc: %v", s)
|
channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: sending update to cc: %v", s)
|
||||||
if channelz.IsOn() {
|
if channelz.IsOn() {
|
||||||
ccr.addChannelzTraceEvent(s)
|
ccr.addChannelzTraceEvent(s)
|
||||||
}
|
}
|
||||||
ccr.curState = s
|
ccr.curState = s
|
||||||
ccr.poll(ccr.cc.updateResolverState(ccr.curState, nil))
|
if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState {
|
||||||
|
return balancer.ErrBadResolverState
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ccr *ccResolverWrapper) ReportError(err error) {
|
func (ccr *ccResolverWrapper) ReportError(err error) {
|
||||||
|
|
@ -153,7 +109,7 @@ func (ccr *ccResolverWrapper) ReportError(err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
|
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
|
||||||
ccr.poll(ccr.cc.updateResolverState(resolver.State{}, err))
|
ccr.cc.updateResolverState(resolver.State{}, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAddress is called by the resolver implementation to send addresses to gRPC.
|
// NewAddress is called by the resolver implementation to send addresses to gRPC.
|
||||||
|
|
@ -166,7 +122,7 @@ func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
|
||||||
ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
|
ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
|
||||||
}
|
}
|
||||||
ccr.curState.Addresses = addrs
|
ccr.curState.Addresses = addrs
|
||||||
ccr.poll(ccr.cc.updateResolverState(ccr.curState, nil))
|
ccr.cc.updateResolverState(ccr.curState, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServiceConfig is called by the resolver implementation to send service
|
// NewServiceConfig is called by the resolver implementation to send service
|
||||||
|
|
@ -183,14 +139,13 @@ func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
|
||||||
scpr := parseServiceConfig(sc)
|
scpr := parseServiceConfig(sc)
|
||||||
if scpr.Err != nil {
|
if scpr.Err != nil {
|
||||||
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)
|
||||||
ccr.poll(balancer.ErrBadResolverState)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if channelz.IsOn() {
|
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.poll(ccr.cc.updateResolverState(ccr.curState, nil))
|
ccr.cc.updateResolverState(ccr.curState, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult {
|
func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -430,9 +429,10 @@ func (o ContentSubtypeCallOption) before(c *callInfo) error {
|
||||||
}
|
}
|
||||||
func (o ContentSubtypeCallOption) after(c *callInfo, attempt *csAttempt) {}
|
func (o ContentSubtypeCallOption) after(c *callInfo, attempt *csAttempt) {}
|
||||||
|
|
||||||
// ForceCodec returns a CallOption that will set the given Codec to be
|
// ForceCodec returns a CallOption that will set codec to be used for all
|
||||||
// used for all request and response messages for a call. The result of calling
|
// request and response messages for a call. The result of calling Name() will
|
||||||
// String() will be used as the content-subtype in a case-insensitive manner.
|
// be used as the content-subtype after converting to lowercase, unless
|
||||||
|
// CallContentSubtype is also used.
|
||||||
//
|
//
|
||||||
// See Content-Type on
|
// See Content-Type on
|
||||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
|
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
|
||||||
|
|
@ -854,7 +854,17 @@ func toRPCErr(err error) error {
|
||||||
// setCallInfoCodec should only be called after CallOptions have been applied.
|
// setCallInfoCodec should only be called after CallOptions have been applied.
|
||||||
func setCallInfoCodec(c *callInfo) error {
|
func setCallInfoCodec(c *callInfo) error {
|
||||||
if c.codec != nil {
|
if c.codec != nil {
|
||||||
// codec was already set by a CallOption; use it.
|
// codec was already set by a CallOption; use it, but set the content
|
||||||
|
// subtype if it is not set.
|
||||||
|
if c.contentSubtype == "" {
|
||||||
|
// c.codec is a baseCodec to hide the difference between grpc.Codec and
|
||||||
|
// encoding.Codec (Name vs. String method name). We only support
|
||||||
|
// setting content subtype from encoding.Codec to avoid a behavior
|
||||||
|
// change with the deprecated version.
|
||||||
|
if ec, ok := c.codec.(encoding.Codec); ok {
|
||||||
|
c.contentSubtype = strings.ToLower(ec.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -872,40 +882,6 @@ func setCallInfoCodec(c *callInfo) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseDialTarget returns the network and address to pass to dialer
|
|
||||||
func parseDialTarget(target string) (net string, addr string) {
|
|
||||||
net = "tcp"
|
|
||||||
|
|
||||||
m1 := strings.Index(target, ":")
|
|
||||||
m2 := strings.Index(target, ":/")
|
|
||||||
|
|
||||||
// handle unix:addr which will fail with url.Parse
|
|
||||||
if m1 >= 0 && m2 < 0 {
|
|
||||||
if n := target[0:m1]; n == "unix" {
|
|
||||||
net = n
|
|
||||||
addr = target[m1+1:]
|
|
||||||
return net, addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if m2 >= 0 {
|
|
||||||
t, err := url.Parse(target)
|
|
||||||
if err != nil {
|
|
||||||
return net, target
|
|
||||||
}
|
|
||||||
scheme := t.Scheme
|
|
||||||
addr = t.Path
|
|
||||||
if scheme == "unix" {
|
|
||||||
net = scheme
|
|
||||||
if addr == "" {
|
|
||||||
addr = t.Host
|
|
||||||
}
|
|
||||||
return net, addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return net, target
|
|
||||||
}
|
|
||||||
|
|
||||||
// channelzData is used to store channelz related data for ClientConn, addrConn and Server.
|
// channelzData is used to store channelz related data for ClientConn, addrConn and Server.
|
||||||
// These fields cannot be embedded in the original structs (e.g. ClientConn), since to do atomic
|
// These fields cannot be embedded in the original structs (e.g. ClientConn), since to do atomic
|
||||||
// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
|
// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
|
||||||
|
|
@ -923,8 +899,7 @@ type channelzData struct {
|
||||||
// buffer files to ensure compatibility with the gRPC version used. The latest
|
// buffer files to ensure compatibility with the gRPC version used. The latest
|
||||||
// support package version is 7.
|
// support package version is 7.
|
||||||
//
|
//
|
||||||
// Older versions are kept for compatibility. They may be removed if
|
// Older versions are kept for compatibility.
|
||||||
// compatibility cannot be maintained.
|
|
||||||
//
|
//
|
||||||
// These constants should not be referenced from any other code.
|
// These constants should not be referenced from any other code.
|
||||||
const (
|
const (
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import (
|
||||||
"google.golang.org/grpc/encoding"
|
"google.golang.org/grpc/encoding"
|
||||||
"google.golang.org/grpc/encoding/proto"
|
"google.golang.org/grpc/encoding/proto"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
|
"google.golang.org/grpc/internal"
|
||||||
"google.golang.org/grpc/internal/binarylog"
|
"google.golang.org/grpc/internal/binarylog"
|
||||||
"google.golang.org/grpc/internal/channelz"
|
"google.golang.org/grpc/internal/channelz"
|
||||||
"google.golang.org/grpc/internal/grpcrand"
|
"google.golang.org/grpc/internal/grpcrand"
|
||||||
|
|
@ -56,8 +57,24 @@ import (
|
||||||
const (
|
const (
|
||||||
defaultServerMaxReceiveMessageSize = 1024 * 1024 * 4
|
defaultServerMaxReceiveMessageSize = 1024 * 1024 * 4
|
||||||
defaultServerMaxSendMessageSize = math.MaxInt32
|
defaultServerMaxSendMessageSize = math.MaxInt32
|
||||||
|
|
||||||
|
// Server transports are tracked in a map which is keyed on listener
|
||||||
|
// address. For regular gRPC traffic, connections are accepted in Serve()
|
||||||
|
// through a call to Accept(), and we use the actual listener address as key
|
||||||
|
// when we add it to the map. But for connections received through
|
||||||
|
// ServeHTTP(), we do not have a listener and hence use this dummy value.
|
||||||
|
listenerAddressForServeHTTP = "listenerAddressForServeHTTP"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
internal.GetServerCredentials = func(srv *Server) credentials.TransportCredentials {
|
||||||
|
return srv.opts.creds
|
||||||
|
}
|
||||||
|
internal.DrainServerTransports = func(srv *Server, addr string) {
|
||||||
|
srv.drainServerTransports(addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var statusOK = status.New(codes.OK, "")
|
var statusOK = status.New(codes.OK, "")
|
||||||
var logger = grpclog.Component("core")
|
var logger = grpclog.Component("core")
|
||||||
|
|
||||||
|
|
@ -102,7 +119,10 @@ type Server struct {
|
||||||
|
|
||||||
mu sync.Mutex // guards following
|
mu sync.Mutex // guards following
|
||||||
lis map[net.Listener]bool
|
lis map[net.Listener]bool
|
||||||
conns map[transport.ServerTransport]bool
|
// conns contains all active server transports. It is a map keyed on a
|
||||||
|
// listener address with the value being the set of active transports
|
||||||
|
// belonging to that listener.
|
||||||
|
conns map[string]map[transport.ServerTransport]bool
|
||||||
serve bool
|
serve bool
|
||||||
drain bool
|
drain bool
|
||||||
cv *sync.Cond // signaled when connections close for GracefulStop
|
cv *sync.Cond // signaled when connections close for GracefulStop
|
||||||
|
|
@ -259,6 +279,35 @@ func CustomCodec(codec Codec) ServerOption {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForceServerCodec returns a ServerOption that sets a codec for message
|
||||||
|
// marshaling and unmarshaling.
|
||||||
|
//
|
||||||
|
// This will override any lookups by content-subtype for Codecs registered
|
||||||
|
// with RegisterCodec.
|
||||||
|
//
|
||||||
|
// See Content-Type on
|
||||||
|
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
|
||||||
|
// more details. Also see the documentation on RegisterCodec and
|
||||||
|
// CallContentSubtype for more details on the interaction between encoding.Codec
|
||||||
|
// and content-subtype.
|
||||||
|
//
|
||||||
|
// This function is provided for advanced users; prefer to register codecs
|
||||||
|
// using encoding.RegisterCodec.
|
||||||
|
// The server will automatically use registered codecs based on the incoming
|
||||||
|
// requests' headers. See also
|
||||||
|
// https://github.com/grpc/grpc-go/blob/master/Documentation/encoding.md#using-a-codec.
|
||||||
|
// Will be supported throughout 1.x.
|
||||||
|
//
|
||||||
|
// Experimental
|
||||||
|
//
|
||||||
|
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||||
|
// later release.
|
||||||
|
func ForceServerCodec(codec encoding.Codec) ServerOption {
|
||||||
|
return newFuncServerOption(func(o *serverOptions) {
|
||||||
|
o.codec = codec
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// RPCCompressor returns a ServerOption that sets a compressor for outbound
|
// RPCCompressor returns a ServerOption that sets a compressor for outbound
|
||||||
// messages. For backward compatibility, all outbound messages will be sent
|
// messages. For backward compatibility, all outbound messages will be sent
|
||||||
// using this compressor, regardless of incoming message compression. By
|
// using this compressor, regardless of incoming message compression. By
|
||||||
|
|
@ -369,6 +418,11 @@ func ChainStreamInterceptor(interceptors ...StreamServerInterceptor) ServerOptio
|
||||||
|
|
||||||
// InTapHandle returns a ServerOption that sets the tap handle for all the server
|
// InTapHandle returns a ServerOption that sets the tap handle for all the server
|
||||||
// transport to be created. Only one can be installed.
|
// transport to be created. Only one can be installed.
|
||||||
|
//
|
||||||
|
// Experimental
|
||||||
|
//
|
||||||
|
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||||
|
// later release.
|
||||||
func InTapHandle(h tap.ServerInHandle) ServerOption {
|
func InTapHandle(h tap.ServerInHandle) ServerOption {
|
||||||
return newFuncServerOption(func(o *serverOptions) {
|
return newFuncServerOption(func(o *serverOptions) {
|
||||||
if o.inTapHandle != nil {
|
if o.inTapHandle != nil {
|
||||||
|
|
@ -512,7 +566,7 @@ func NewServer(opt ...ServerOption) *Server {
|
||||||
s := &Server{
|
s := &Server{
|
||||||
lis: make(map[net.Listener]bool),
|
lis: make(map[net.Listener]bool),
|
||||||
opts: opts,
|
opts: opts,
|
||||||
conns: make(map[transport.ServerTransport]bool),
|
conns: make(map[string]map[transport.ServerTransport]bool),
|
||||||
services: make(map[string]*serviceInfo),
|
services: make(map[string]*serviceInfo),
|
||||||
quit: grpcsync.NewEvent(),
|
quit: grpcsync.NewEvent(),
|
||||||
done: grpcsync.NewEvent(),
|
done: grpcsync.NewEvent(),
|
||||||
|
|
@ -771,7 +825,7 @@ func (s *Server) Serve(lis net.Listener) error {
|
||||||
// s.conns before this conn can be added.
|
// s.conns before this conn can be added.
|
||||||
s.serveWG.Add(1)
|
s.serveWG.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
s.handleRawConn(rawConn)
|
s.handleRawConn(lis.Addr().String(), rawConn)
|
||||||
s.serveWG.Done()
|
s.serveWG.Done()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
@ -779,7 +833,7 @@ func (s *Server) Serve(lis net.Listener) error {
|
||||||
|
|
||||||
// handleRawConn forks a goroutine to handle a just-accepted connection that
|
// handleRawConn forks a goroutine to handle a just-accepted connection that
|
||||||
// has not had any I/O performed on it yet.
|
// has not had any I/O performed on it yet.
|
||||||
func (s *Server) handleRawConn(rawConn net.Conn) {
|
func (s *Server) handleRawConn(lisAddr string, rawConn net.Conn) {
|
||||||
if s.quit.HasFired() {
|
if s.quit.HasFired() {
|
||||||
rawConn.Close()
|
rawConn.Close()
|
||||||
return
|
return
|
||||||
|
|
@ -807,15 +861,24 @@ func (s *Server) handleRawConn(rawConn net.Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rawConn.SetDeadline(time.Time{})
|
rawConn.SetDeadline(time.Time{})
|
||||||
if !s.addConn(st) {
|
if !s.addConn(lisAddr, st) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
s.serveStreams(st)
|
s.serveStreams(st)
|
||||||
s.removeConn(st)
|
s.removeConn(lisAddr, st)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) drainServerTransports(addr string) {
|
||||||
|
s.mu.Lock()
|
||||||
|
conns := s.conns[addr]
|
||||||
|
for st := range conns {
|
||||||
|
st.Drain()
|
||||||
|
}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// 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, authInfo credentials.AuthInfo) transport.ServerTransport {
|
||||||
|
|
@ -917,10 +980,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !s.addConn(st) {
|
if !s.addConn(listenerAddressForServeHTTP, st) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer s.removeConn(st)
|
defer s.removeConn(listenerAddressForServeHTTP, st)
|
||||||
s.serveStreams(st)
|
s.serveStreams(st)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -948,7 +1011,7 @@ func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Strea
|
||||||
return trInfo
|
return trInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) addConn(st transport.ServerTransport) bool {
|
func (s *Server) addConn(addr string, st transport.ServerTransport) bool {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
if s.conns == nil {
|
if s.conns == nil {
|
||||||
|
|
@ -960,15 +1023,28 @@ func (s *Server) addConn(st transport.ServerTransport) bool {
|
||||||
// immediately.
|
// immediately.
|
||||||
st.Drain()
|
st.Drain()
|
||||||
}
|
}
|
||||||
s.conns[st] = true
|
|
||||||
|
if s.conns[addr] == nil {
|
||||||
|
// Create a map entry if this is the first connection on this listener.
|
||||||
|
s.conns[addr] = make(map[transport.ServerTransport]bool)
|
||||||
|
}
|
||||||
|
s.conns[addr][st] = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) removeConn(st transport.ServerTransport) {
|
func (s *Server) removeConn(addr string, st transport.ServerTransport) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
if s.conns != nil {
|
|
||||||
delete(s.conns, st)
|
conns := s.conns[addr]
|
||||||
|
if conns != nil {
|
||||||
|
delete(conns, st)
|
||||||
|
if len(conns) == 0 {
|
||||||
|
// If the last connection for this address is being removed, also
|
||||||
|
// remove the map entry corresponding to the address. This is used
|
||||||
|
// in GracefulStop() when waiting for all connections to be closed.
|
||||||
|
delete(s.conns, addr)
|
||||||
|
}
|
||||||
s.cv.Broadcast()
|
s.cv.Broadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1632,7 +1708,7 @@ func (s *Server) Stop() {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
listeners := s.lis
|
listeners := s.lis
|
||||||
s.lis = nil
|
s.lis = nil
|
||||||
st := s.conns
|
conns := s.conns
|
||||||
s.conns = nil
|
s.conns = nil
|
||||||
// interrupt GracefulStop if Stop and GracefulStop are called concurrently.
|
// interrupt GracefulStop if Stop and GracefulStop are called concurrently.
|
||||||
s.cv.Broadcast()
|
s.cv.Broadcast()
|
||||||
|
|
@ -1641,8 +1717,10 @@ func (s *Server) Stop() {
|
||||||
for lis := range listeners {
|
for lis := range listeners {
|
||||||
lis.Close()
|
lis.Close()
|
||||||
}
|
}
|
||||||
for c := range st {
|
for _, cs := range conns {
|
||||||
c.Close()
|
for st := range cs {
|
||||||
|
st.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if s.opts.numServerWorkers > 0 {
|
if s.opts.numServerWorkers > 0 {
|
||||||
s.stopServerWorkers()
|
s.stopServerWorkers()
|
||||||
|
|
@ -1679,9 +1757,11 @@ func (s *Server) GracefulStop() {
|
||||||
}
|
}
|
||||||
s.lis = nil
|
s.lis = nil
|
||||||
if !s.drain {
|
if !s.drain {
|
||||||
for st := range s.conns {
|
for _, conns := range s.conns {
|
||||||
|
for st := range conns {
|
||||||
st.Drain()
|
st.Drain()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
s.drain = true
|
s.drain = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,29 +41,7 @@ const maxInt = int(^uint(0) >> 1)
|
||||||
// Deprecated: Users should not use this struct. Service config should be received
|
// Deprecated: Users should not use this struct. Service config should be received
|
||||||
// through name resolver, as specified here
|
// through name resolver, as specified here
|
||||||
// https://github.com/grpc/grpc/blob/master/doc/service_config.md
|
// https://github.com/grpc/grpc/blob/master/doc/service_config.md
|
||||||
type MethodConfig struct {
|
type MethodConfig = internalserviceconfig.MethodConfig
|
||||||
// WaitForReady indicates whether RPCs sent to this method should wait until
|
|
||||||
// the connection is ready by default (!failfast). The value specified via the
|
|
||||||
// gRPC client API will override the value set here.
|
|
||||||
WaitForReady *bool
|
|
||||||
// Timeout is the default timeout for RPCs sent to this method. The actual
|
|
||||||
// deadline used will be the minimum of the value specified here and the value
|
|
||||||
// set by the application via the gRPC client API. If either one is not set,
|
|
||||||
// then the other will be used. If neither is set, then the RPC has no deadline.
|
|
||||||
Timeout *time.Duration
|
|
||||||
// MaxReqSize is the maximum allowed payload size for an individual request in a
|
|
||||||
// stream (client->server) in bytes. The size which is measured is the serialized
|
|
||||||
// payload after per-message compression (but before stream compression) in bytes.
|
|
||||||
// The actual value used is the minimum of the value specified here and the value set
|
|
||||||
// by the application via the gRPC client API. If either one is not set, then the other
|
|
||||||
// will be used. If neither is set, then the built-in default is used.
|
|
||||||
MaxReqSize *int
|
|
||||||
// MaxRespSize is the maximum allowed payload size for an individual response in a
|
|
||||||
// stream (server->client) in bytes.
|
|
||||||
MaxRespSize *int
|
|
||||||
// RetryPolicy configures retry options for the method.
|
|
||||||
retryPolicy *retryPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
type lbConfig struct {
|
type lbConfig struct {
|
||||||
name string
|
name string
|
||||||
|
|
@ -127,34 +105,6 @@ type healthCheckConfig struct {
|
||||||
ServiceName string
|
ServiceName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// retryPolicy defines the go-native version of the retry policy defined by the
|
|
||||||
// service config here:
|
|
||||||
// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#integration-with-service-config
|
|
||||||
type retryPolicy struct {
|
|
||||||
// MaxAttempts is the maximum number of attempts, including the original RPC.
|
|
||||||
//
|
|
||||||
// This field is required and must be two or greater.
|
|
||||||
maxAttempts int
|
|
||||||
|
|
||||||
// Exponential backoff parameters. The initial retry attempt will occur at
|
|
||||||
// random(0, initialBackoff). In general, the nth attempt will occur at
|
|
||||||
// random(0,
|
|
||||||
// min(initialBackoff*backoffMultiplier**(n-1), maxBackoff)).
|
|
||||||
//
|
|
||||||
// These fields are required and must be greater than zero.
|
|
||||||
initialBackoff time.Duration
|
|
||||||
maxBackoff time.Duration
|
|
||||||
backoffMultiplier float64
|
|
||||||
|
|
||||||
// The set of status codes which may be retried.
|
|
||||||
//
|
|
||||||
// Status codes are specified as strings, e.g., "UNAVAILABLE".
|
|
||||||
//
|
|
||||||
// This field is required and must be non-empty.
|
|
||||||
// Note: a set is used to store this for easy lookup.
|
|
||||||
retryableStatusCodes map[codes.Code]bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type jsonRetryPolicy struct {
|
type jsonRetryPolicy struct {
|
||||||
MaxAttempts int
|
MaxAttempts int
|
||||||
InitialBackoff string
|
InitialBackoff string
|
||||||
|
|
@ -313,7 +263,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
|
||||||
WaitForReady: m.WaitForReady,
|
WaitForReady: m.WaitForReady,
|
||||||
Timeout: d,
|
Timeout: d,
|
||||||
}
|
}
|
||||||
if mc.retryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil {
|
if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil {
|
||||||
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
|
logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
|
||||||
return &serviceconfig.ParseResult{Err: err}
|
return &serviceconfig.ParseResult{Err: err}
|
||||||
}
|
}
|
||||||
|
|
@ -359,7 +309,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult {
|
||||||
return &serviceconfig.ParseResult{Config: &sc}
|
return &serviceconfig.ParseResult{Config: &sc}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertRetryPolicy(jrp *jsonRetryPolicy) (p *retryPolicy, err error) {
|
func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPolicy, err error) {
|
||||||
if jrp == nil {
|
if jrp == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -381,19 +331,19 @@ func convertRetryPolicy(jrp *jsonRetryPolicy) (p *retryPolicy, err error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rp := &retryPolicy{
|
rp := &internalserviceconfig.RetryPolicy{
|
||||||
maxAttempts: jrp.MaxAttempts,
|
MaxAttempts: jrp.MaxAttempts,
|
||||||
initialBackoff: *ib,
|
InitialBackoff: *ib,
|
||||||
maxBackoff: *mb,
|
MaxBackoff: *mb,
|
||||||
backoffMultiplier: jrp.BackoffMultiplier,
|
BackoffMultiplier: jrp.BackoffMultiplier,
|
||||||
retryableStatusCodes: make(map[codes.Code]bool),
|
RetryableStatusCodes: make(map[codes.Code]bool),
|
||||||
}
|
}
|
||||||
if rp.maxAttempts > 5 {
|
if rp.MaxAttempts > 5 {
|
||||||
// TODO(retry): Make the max maxAttempts configurable.
|
// TODO(retry): Make the max maxAttempts configurable.
|
||||||
rp.maxAttempts = 5
|
rp.MaxAttempts = 5
|
||||||
}
|
}
|
||||||
for _, code := range jrp.RetryableStatusCodes {
|
for _, code := range jrp.RetryableStatusCodes {
|
||||||
rp.retryableStatusCodes[code] = true
|
rp.RetryableStatusCodes[code] = true
|
||||||
}
|
}
|
||||||
return rp, nil
|
return rp, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,11 @@ func FromProto(s *spb.Status) *Status {
|
||||||
return status.FromProto(s)
|
return status.FromProto(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromError returns a Status representing err if it was produced from this
|
// FromError returns a Status representing err if it was produced by this
|
||||||
// package or has a method `GRPCStatus() *Status`. Otherwise, ok is false and a
|
// package or has a method `GRPCStatus() *Status`.
|
||||||
// Status is returned with codes.Unknown and the original error message.
|
// If err is nil, a Status is returned with codes.OK and no message.
|
||||||
|
// Otherwise, ok is false and a Status is returned with codes.Unknown and
|
||||||
|
// the original error message.
|
||||||
func FromError(err error) (s *Status, ok bool) {
|
func FromError(err error) (s *Status, ok bool) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil, true
|
return nil, true
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ import (
|
||||||
"google.golang.org/grpc/internal/channelz"
|
"google.golang.org/grpc/internal/channelz"
|
||||||
"google.golang.org/grpc/internal/grpcrand"
|
"google.golang.org/grpc/internal/grpcrand"
|
||||||
"google.golang.org/grpc/internal/grpcutil"
|
"google.golang.org/grpc/internal/grpcutil"
|
||||||
|
iresolver "google.golang.org/grpc/internal/resolver"
|
||||||
|
"google.golang.org/grpc/internal/serviceconfig"
|
||||||
"google.golang.org/grpc/internal/transport"
|
"google.golang.org/grpc/internal/transport"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
|
|
@ -50,14 +52,20 @@ import (
|
||||||
// of the RPC.
|
// of the RPC.
|
||||||
type StreamHandler func(srv interface{}, stream ServerStream) error
|
type StreamHandler func(srv interface{}, stream ServerStream) error
|
||||||
|
|
||||||
// StreamDesc represents a streaming RPC service's method specification.
|
// StreamDesc represents a streaming RPC service's method specification. Used
|
||||||
|
// on the server when registering services and on the client when initiating
|
||||||
|
// new streams.
|
||||||
type StreamDesc struct {
|
type StreamDesc struct {
|
||||||
StreamName string
|
// StreamName and Handler are only used when registering handlers on a
|
||||||
Handler StreamHandler
|
// server.
|
||||||
|
StreamName string // the name of the method excluding the service
|
||||||
|
Handler StreamHandler // the handler called for the method
|
||||||
|
|
||||||
// At least one of these is true.
|
// ServerStreams and ClientStreams are used for registering handlers on a
|
||||||
ServerStreams bool
|
// server as well as defining RPC behavior when passed to NewClientStream
|
||||||
ClientStreams bool
|
// and ClientConn.NewStream. At least one must be true.
|
||||||
|
ServerStreams bool // indicates the server can perform streaming sends
|
||||||
|
ClientStreams bool // indicates the client can perform streaming sends
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stream defines the common interface a client or server stream has to satisfy.
|
// Stream defines the common interface a client or server stream has to satisfy.
|
||||||
|
|
@ -164,13 +172,48 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
c := defaultCallInfo()
|
|
||||||
// Provide an opportunity for the first RPC to see the first service config
|
// Provide an opportunity for the first RPC to see the first service config
|
||||||
// provided by the resolver.
|
// provided by the resolver.
|
||||||
if err := cc.waitForResolvedAddrs(ctx); err != nil {
|
if err := cc.waitForResolvedAddrs(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
mc := cc.GetMethodConfig(method)
|
|
||||||
|
var mc serviceconfig.MethodConfig
|
||||||
|
var onCommit func()
|
||||||
|
var newStream = func(ctx context.Context, done func()) (iresolver.ClientStream, error) {
|
||||||
|
return newClientStreamWithParams(ctx, desc, cc, method, mc, onCommit, done, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcInfo := iresolver.RPCInfo{Context: ctx, Method: method}
|
||||||
|
rpcConfig, err := cc.safeConfigSelector.SelectConfig(rpcInfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, toRPCErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rpcConfig != nil {
|
||||||
|
if rpcConfig.Context != nil {
|
||||||
|
ctx = rpcConfig.Context
|
||||||
|
}
|
||||||
|
mc = rpcConfig.MethodConfig
|
||||||
|
onCommit = rpcConfig.OnCommitted
|
||||||
|
if rpcConfig.Interceptor != nil {
|
||||||
|
rpcInfo.Context = nil
|
||||||
|
ns := newStream
|
||||||
|
newStream = func(ctx context.Context, done func()) (iresolver.ClientStream, error) {
|
||||||
|
cs, err := rpcConfig.Interceptor.NewStream(ctx, rpcInfo, done, ns)
|
||||||
|
if err != nil {
|
||||||
|
return nil, toRPCErr(err)
|
||||||
|
}
|
||||||
|
return cs, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newStream(ctx, func() {})
|
||||||
|
}
|
||||||
|
|
||||||
|
func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, mc serviceconfig.MethodConfig, onCommit, doneFunc func(), opts ...CallOption) (_ iresolver.ClientStream, err error) {
|
||||||
|
c := defaultCallInfo()
|
||||||
if mc.WaitForReady != nil {
|
if mc.WaitForReady != nil {
|
||||||
c.failFast = !*mc.WaitForReady
|
c.failFast = !*mc.WaitForReady
|
||||||
}
|
}
|
||||||
|
|
@ -207,6 +250,7 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
|
||||||
Host: cc.authority,
|
Host: cc.authority,
|
||||||
Method: method,
|
Method: method,
|
||||||
ContentSubtype: c.contentSubtype,
|
ContentSubtype: c.contentSubtype,
|
||||||
|
DoneFunc: doneFunc,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set our outgoing compression according to the UseCompressor CallOption, if
|
// Set our outgoing compression according to the UseCompressor CallOption, if
|
||||||
|
|
@ -272,6 +316,7 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
beginTime: beginTime,
|
beginTime: beginTime,
|
||||||
firstAttempt: true,
|
firstAttempt: true,
|
||||||
|
onCommit: onCommit,
|
||||||
}
|
}
|
||||||
if !cc.dopts.disableRetry {
|
if !cc.dopts.disableRetry {
|
||||||
cs.retryThrottler = cc.retryThrottler.Load().(*retryThrottler)
|
cs.retryThrottler = cc.retryThrottler.Load().(*retryThrottler)
|
||||||
|
|
@ -433,6 +478,7 @@ type clientStream struct {
|
||||||
attempt *csAttempt
|
attempt *csAttempt
|
||||||
// TODO(hedging): hedging will have multiple attempts simultaneously.
|
// TODO(hedging): hedging will have multiple attempts simultaneously.
|
||||||
committed bool // active attempt committed for retry?
|
committed bool // active attempt committed for retry?
|
||||||
|
onCommit func()
|
||||||
buffer []func(a *csAttempt) error // operations to replay on retry
|
buffer []func(a *csAttempt) error // operations to replay on retry
|
||||||
bufferSize int // current size of buffer
|
bufferSize int // current size of buffer
|
||||||
}
|
}
|
||||||
|
|
@ -461,6 +507,9 @@ type csAttempt struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *clientStream) commitAttemptLocked() {
|
func (cs *clientStream) commitAttemptLocked() {
|
||||||
|
if !cs.committed && cs.onCommit != nil {
|
||||||
|
cs.onCommit()
|
||||||
|
}
|
||||||
cs.committed = true
|
cs.committed = true
|
||||||
cs.buffer = nil
|
cs.buffer = nil
|
||||||
}
|
}
|
||||||
|
|
@ -539,8 +588,8 @@ func (cs *clientStream) shouldRetry(err error) error {
|
||||||
code = status.Convert(err).Code()
|
code = status.Convert(err).Code()
|
||||||
}
|
}
|
||||||
|
|
||||||
rp := cs.methodConfig.retryPolicy
|
rp := cs.methodConfig.RetryPolicy
|
||||||
if rp == nil || !rp.retryableStatusCodes[code] {
|
if rp == nil || !rp.RetryableStatusCodes[code] {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -549,7 +598,7 @@ func (cs *clientStream) shouldRetry(err error) error {
|
||||||
if cs.retryThrottler.throttle() {
|
if cs.retryThrottler.throttle() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if cs.numRetries+1 >= rp.maxAttempts {
|
if cs.numRetries+1 >= rp.MaxAttempts {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -558,9 +607,9 @@ func (cs *clientStream) shouldRetry(err error) error {
|
||||||
dur = time.Millisecond * time.Duration(pushback)
|
dur = time.Millisecond * time.Duration(pushback)
|
||||||
cs.numRetriesSincePushback = 0
|
cs.numRetriesSincePushback = 0
|
||||||
} else {
|
} else {
|
||||||
fact := math.Pow(rp.backoffMultiplier, float64(cs.numRetriesSincePushback))
|
fact := math.Pow(rp.BackoffMultiplier, float64(cs.numRetriesSincePushback))
|
||||||
cur := float64(rp.initialBackoff) * fact
|
cur := float64(rp.InitialBackoff) * fact
|
||||||
if max := float64(rp.maxBackoff); cur > max {
|
if max := float64(rp.MaxBackoff); cur > max {
|
||||||
cur = max
|
cur = max
|
||||||
}
|
}
|
||||||
dur = time.Duration(grpcrand.Int63n(int64(cur)))
|
dur = time.Duration(grpcrand.Int63n(int64(cur)))
|
||||||
|
|
|
||||||
|
|
@ -37,16 +37,16 @@ type Info struct {
|
||||||
// TODO: More to be added.
|
// TODO: More to be added.
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerInHandle defines the function which runs before a new stream is created
|
// ServerInHandle defines the function which runs before a new stream is
|
||||||
// on the server side. If it returns a non-nil error, the stream will not be
|
// created on the server side. If it returns a non-nil error, the stream will
|
||||||
// created and a RST_STREAM will be sent back to the client with REFUSED_STREAM.
|
// not be created and an error will be returned to the client. If the error
|
||||||
// The client will receive an RPC error "code = Unavailable, desc = stream
|
// returned is a status error, that status code and message will be used,
|
||||||
// terminated by RST_STREAM with error code: REFUSED_STREAM".
|
// otherwise PermissionDenied will be the code and err.Error() will be the
|
||||||
|
// message.
|
||||||
//
|
//
|
||||||
// It's intended to be used in situations where you don't want to waste the
|
// It's intended to be used in situations where you don't want to waste the
|
||||||
// resources to accept the new stream (e.g. rate-limiting). And the content of
|
// resources to accept the new stream (e.g. rate-limiting). For other general
|
||||||
// the error will be ignored and won't be sent back to the client. For other
|
// usages, please use interceptors.
|
||||||
// general usages, please use interceptors.
|
|
||||||
//
|
//
|
||||||
// Note that it is executed in the per-connection I/O goroutine(s) instead of
|
// Note that it is executed in the per-connection I/O goroutine(s) instead of
|
||||||
// per-RPC goroutine. Therefore, users should NOT have any
|
// per-RPC goroutine. Therefore, users should NOT have any
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,4 @@
|
||||||
package grpc
|
package grpc
|
||||||
|
|
||||||
// Version is the current grpc version.
|
// Version is the current grpc version.
|
||||||
const Version = "1.33.2"
|
const Version = "1.38.0"
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ cleanup() {
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"
|
PATH="${HOME}/go/bin:${GOROOT}/bin:${PATH}"
|
||||||
|
go version
|
||||||
|
|
||||||
if [[ "$1" = "-install" ]]; then
|
if [[ "$1" = "-install" ]]; then
|
||||||
# Check for module support
|
# Check for module support
|
||||||
|
|
@ -53,7 +54,7 @@ if [[ "$1" = "-install" ]]; then
|
||||||
fi
|
fi
|
||||||
if [[ -z "${VET_SKIP_PROTO}" ]]; then
|
if [[ -z "${VET_SKIP_PROTO}" ]]; then
|
||||||
if [[ "${TRAVIS}" = "true" ]]; then
|
if [[ "${TRAVIS}" = "true" ]]; then
|
||||||
PROTOBUF_VERSION=3.3.0
|
PROTOBUF_VERSION=3.14.0
|
||||||
PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
|
PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
|
||||||
pushd /home/travis
|
pushd /home/travis
|
||||||
wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
|
wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
|
||||||
|
|
@ -61,7 +62,7 @@ if [[ "$1" = "-install" ]]; then
|
||||||
bin/protoc --version
|
bin/protoc --version
|
||||||
popd
|
popd
|
||||||
elif [[ "${GITHUB_ACTIONS}" = "true" ]]; then
|
elif [[ "${GITHUB_ACTIONS}" = "true" ]]; then
|
||||||
PROTOBUF_VERSION=3.3.0
|
PROTOBUF_VERSION=3.14.0
|
||||||
PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
|
PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
|
||||||
pushd /home/runner/go
|
pushd /home/runner/go
|
||||||
wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
|
wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
|
||||||
|
|
@ -104,12 +105,6 @@ git grep '"github.com/envoyproxy/go-control-plane/envoy' -- '*.go' ':(exclude)*.
|
||||||
# TODO: Remove when we drop Go 1.10 support
|
# TODO: Remove when we drop Go 1.10 support
|
||||||
go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go
|
go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go
|
||||||
|
|
||||||
# - gofmt, goimports, golint (with exceptions for generated code), go vet.
|
|
||||||
gofmt -s -d -l . 2>&1 | fail_on_output
|
|
||||||
goimports -l . 2>&1 | not grep -vE "\.pb\.go"
|
|
||||||
golint ./... 2>&1 | not grep -vE "\.pb\.go:"
|
|
||||||
go vet -all ./...
|
|
||||||
|
|
||||||
misspell -error .
|
misspell -error .
|
||||||
|
|
||||||
# - Check that generated proto files are up to date.
|
# - Check that generated proto files are up to date.
|
||||||
|
|
@ -119,12 +114,22 @@ if [[ -z "${VET_SKIP_PROTO}" ]]; then
|
||||||
(git status; git --no-pager diff; exit 1)
|
(git status; git --no-pager diff; exit 1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# - Check that our modules are tidy.
|
# - gofmt, goimports, golint (with exceptions for generated code), go vet,
|
||||||
if go help mod >& /dev/null; then
|
# go mod tidy.
|
||||||
find . -name 'go.mod' | xargs -IXXX bash -c 'cd $(dirname XXX); go mod tidy'
|
# Perform these checks on each module inside gRPC.
|
||||||
|
for MOD_FILE in $(find . -name 'go.mod'); do
|
||||||
|
MOD_DIR=$(dirname ${MOD_FILE})
|
||||||
|
pushd ${MOD_DIR}
|
||||||
|
go vet -all ./... | fail_on_output
|
||||||
|
gofmt -s -d -l . 2>&1 | fail_on_output
|
||||||
|
goimports -l . 2>&1 | not grep -vE "\.pb\.go"
|
||||||
|
golint ./... 2>&1 | not grep -vE "/testv3\.pb\.go:"
|
||||||
|
|
||||||
|
go mod tidy
|
||||||
git status --porcelain 2>&1 | fail_on_output || \
|
git status --porcelain 2>&1 | fail_on_output || \
|
||||||
(git status; git --no-pager diff; exit 1)
|
(git status; git --no-pager diff; exit 1)
|
||||||
fi
|
popd
|
||||||
|
done
|
||||||
|
|
||||||
# - Collection of static analysis checks
|
# - Collection of static analysis checks
|
||||||
#
|
#
|
||||||
|
|
@ -141,8 +146,11 @@ not grep -Fv '.CredsBundle
|
||||||
.NewAddress
|
.NewAddress
|
||||||
.NewServiceConfig
|
.NewServiceConfig
|
||||||
.Type is deprecated: use Attributes
|
.Type is deprecated: use Attributes
|
||||||
|
BuildVersion is deprecated
|
||||||
balancer.ErrTransientFailure
|
balancer.ErrTransientFailure
|
||||||
balancer.Picker
|
balancer.Picker
|
||||||
|
extDesc.Filename is deprecated
|
||||||
|
github.com/golang/protobuf/jsonpb is deprecated
|
||||||
grpc.CallCustomCodec
|
grpc.CallCustomCodec
|
||||||
grpc.Code
|
grpc.Code
|
||||||
grpc.Compressor
|
grpc.Compressor
|
||||||
|
|
@ -164,13 +172,7 @@ grpc.WithServiceConfig
|
||||||
grpc.WithTimeout
|
grpc.WithTimeout
|
||||||
http.CloseNotifier
|
http.CloseNotifier
|
||||||
info.SecurityVersion
|
info.SecurityVersion
|
||||||
resolver.Backend
|
|
||||||
resolver.GRPCLB
|
|
||||||
extDesc.Filename is deprecated
|
|
||||||
BuildVersion is deprecated
|
|
||||||
github.com/golang/protobuf/jsonpb is deprecated
|
|
||||||
proto is deprecated
|
proto is deprecated
|
||||||
xxx_messageInfo_
|
|
||||||
proto.InternalMessageInfo is deprecated
|
proto.InternalMessageInfo is deprecated
|
||||||
proto.EnumName is deprecated
|
proto.EnumName is deprecated
|
||||||
proto.ErrInternalBadWireType is deprecated
|
proto.ErrInternalBadWireType is deprecated
|
||||||
|
|
@ -184,7 +186,12 @@ proto.RegisterExtension is deprecated
|
||||||
proto.RegisteredExtension is deprecated
|
proto.RegisteredExtension is deprecated
|
||||||
proto.RegisteredExtensions is deprecated
|
proto.RegisteredExtensions is deprecated
|
||||||
proto.RegisterMapType is deprecated
|
proto.RegisterMapType is deprecated
|
||||||
proto.Unmarshaler is deprecated' "${SC_OUT}"
|
proto.Unmarshaler is deprecated
|
||||||
|
resolver.Backend
|
||||||
|
resolver.GRPCLB
|
||||||
|
Target is deprecated: Use the Target field in the BuildOptions instead.
|
||||||
|
xxx_messageInfo_
|
||||||
|
' "${SC_OUT}"
|
||||||
|
|
||||||
# - special golint on package comments.
|
# - special golint on package comments.
|
||||||
lint_package_comment_per_package() {
|
lint_package_comment_per_package() {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.4.x"
|
|
||||||
- "1.5.x"
|
|
||||||
- "1.6.x"
|
|
||||||
- "1.7.x"
|
|
||||||
- "1.8.x"
|
|
||||||
- "1.9.x"
|
|
||||||
- "1.10.x"
|
|
||||||
- "1.11.x"
|
|
||||||
- "1.12.x"
|
|
||||||
- "1.13.x"
|
|
||||||
- "1.14.x"
|
|
||||||
- "tip"
|
|
||||||
|
|
||||||
go_import_path: gopkg.in/yaml.v3
|
|
||||||
|
|
@ -399,7 +399,7 @@ func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good
|
||||||
//
|
//
|
||||||
// If n holds a null value, prepare returns before doing anything.
|
// If n holds a null value, prepare returns before doing anything.
|
||||||
func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
|
func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
|
||||||
if n.ShortTag() == nullTag || n.Kind == 0 && n.IsZero() {
|
if n.ShortTag() == nullTag {
|
||||||
return out, false, false
|
return out, false, false
|
||||||
}
|
}
|
||||||
again := true
|
again := true
|
||||||
|
|
@ -808,8 +808,10 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mapIsNew := false
|
||||||
if out.IsNil() {
|
if out.IsNil() {
|
||||||
out.Set(reflect.MakeMap(outt))
|
out.Set(reflect.MakeMap(outt))
|
||||||
|
mapIsNew = true
|
||||||
}
|
}
|
||||||
for i := 0; i < l; i += 2 {
|
for i := 0; i < l; i += 2 {
|
||||||
if isMerge(n.Content[i]) {
|
if isMerge(n.Content[i]) {
|
||||||
|
|
@ -826,7 +828,7 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
|
||||||
failf("invalid map key: %#v", k.Interface())
|
failf("invalid map key: %#v", k.Interface())
|
||||||
}
|
}
|
||||||
e := reflect.New(et).Elem()
|
e := reflect.New(et).Elem()
|
||||||
if d.unmarshal(n.Content[i+1], e) {
|
if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
|
||||||
out.SetMapIndex(k, e)
|
out.SetMapIndex(k, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -814,26 +814,24 @@ func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(emitter.key_line_comment) > 0 {
|
if len(emitter.key_line_comment) > 0 {
|
||||||
// [Go] A line comment was previously provided for the key. Handle it before
|
// [Go] Line comments are generally associated with the value, but when there's
|
||||||
// the value so the inline comments are placed correctly.
|
// no value on the same line as a mapping key they end up attached to the
|
||||||
if yaml_emitter_silent_nil_event(emitter, event) && len(emitter.line_comment) == 0 {
|
// key itself.
|
||||||
// Nothing other than the line comment will be written on the line.
|
if event.typ == yaml_SCALAR_EVENT {
|
||||||
|
if len(emitter.line_comment) == 0 {
|
||||||
|
// A scalar is coming and it has no line comments by itself yet,
|
||||||
|
// so just let it handle the line comment as usual. If it has a
|
||||||
|
// line comment, we can't have both so the one from the key is lost.
|
||||||
emitter.line_comment = emitter.key_line_comment
|
emitter.line_comment = emitter.key_line_comment
|
||||||
emitter.key_line_comment = nil
|
emitter.key_line_comment = nil
|
||||||
} else {
|
}
|
||||||
// An actual value is coming, so emit the comment line.
|
} else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
|
||||||
|
// An indented block follows, so write the comment right now.
|
||||||
emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
|
emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
|
||||||
if !yaml_emitter_process_line_comment(emitter) {
|
if !yaml_emitter_process_line_comment(emitter) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
|
emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
|
||||||
// Indent in unless it's a block that will reindent anyway.
|
|
||||||
if event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || (event.typ != yaml_MAPPING_START_EVENT && event.typ != yaml_SEQUENCE_START_EVENT) {
|
|
||||||
emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
|
|
||||||
if !yaml_emitter_write_indent(emitter) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
|
emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
|
||||||
|
|
@ -1896,7 +1894,7 @@ func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bo
|
||||||
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
|
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !put_break(emitter) {
|
if !yaml_emitter_process_line_comment(emitter) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
//emitter.indention = true
|
//emitter.indention = true
|
||||||
|
|
@ -1933,10 +1931,10 @@ func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) boo
|
||||||
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
|
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if !yaml_emitter_process_line_comment(emitter) {
|
||||||
if !put_break(emitter) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
//emitter.indention = true
|
//emitter.indention = true
|
||||||
emitter.whitespace = true
|
emitter.whitespace = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,11 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||||
e.nodev(in)
|
e.nodev(in)
|
||||||
return
|
return
|
||||||
case Node:
|
case Node:
|
||||||
|
if !in.CanAddr() {
|
||||||
|
var n = reflect.New(in.Type()).Elem()
|
||||||
|
n.Set(in)
|
||||||
|
in = n
|
||||||
|
}
|
||||||
e.nodev(in.Addr())
|
e.nodev(in.Addr())
|
||||||
return
|
return
|
||||||
case time.Time:
|
case time.Time:
|
||||||
|
|
|
||||||
|
|
@ -2260,10 +2260,9 @@ func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if parser.buffer[parser.buffer_pos] == '#' {
|
if parser.buffer[parser.buffer_pos] == '#' {
|
||||||
// TODO Test this and then re-enable it.
|
if !yaml_parser_scan_line_comment(parser, start_mark) {
|
||||||
//if !yaml_parser_scan_line_comment(parser, start_mark) {
|
return false
|
||||||
// return false
|
}
|
||||||
//}
|
|
||||||
for !is_breakz(parser.buffer, parser.buffer_pos) {
|
for !is_breakz(parser.buffer, parser.buffer_pos) {
|
||||||
skip(parser)
|
skip(parser)
|
||||||
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
||||||
|
|
@ -2892,6 +2891,10 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
|
||||||
|
|
||||||
var token_mark = token.start_mark
|
var token_mark = token.start_mark
|
||||||
var start_mark yaml_mark_t
|
var start_mark yaml_mark_t
|
||||||
|
var next_indent = parser.indent
|
||||||
|
if next_indent < 0 {
|
||||||
|
next_indent = 0
|
||||||
|
}
|
||||||
|
|
||||||
var recent_empty = false
|
var recent_empty = false
|
||||||
var first_empty = parser.newlines <= 1
|
var first_empty = parser.newlines <= 1
|
||||||
|
|
@ -2923,15 +2926,18 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c := parser.buffer[parser.buffer_pos+peek]
|
c := parser.buffer[parser.buffer_pos+peek]
|
||||||
if is_breakz(parser.buffer, parser.buffer_pos+peek) || parser.flow_level > 0 && (c == ']' || c == '}') {
|
var close_flow = parser.flow_level > 0 && (c == ']' || c == '}')
|
||||||
|
if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) {
|
||||||
// Got line break or terminator.
|
// Got line break or terminator.
|
||||||
if !recent_empty {
|
if close_flow || !recent_empty {
|
||||||
if first_empty && (start_mark.line == foot_line || start_mark.column-1 < parser.indent) {
|
if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) {
|
||||||
// This is the first empty line and there were no empty lines before,
|
// This is the first empty line and there were no empty lines before,
|
||||||
// so this initial part of the comment is a foot of the prior token
|
// so this initial part of the comment is a foot of the prior token
|
||||||
// instead of being a head for the following one. Split it up.
|
// instead of being a head for the following one. Split it up.
|
||||||
|
// Alternatively, this might also be the last comment inside a flow
|
||||||
|
// scope, so it must be a footer.
|
||||||
if len(text) > 0 {
|
if len(text) > 0 {
|
||||||
if start_mark.column-1 < parser.indent {
|
if start_mark.column-1 < next_indent {
|
||||||
// If dedented it's unrelated to the prior token.
|
// If dedented it's unrelated to the prior token.
|
||||||
token_mark = start_mark
|
token_mark = start_mark
|
||||||
}
|
}
|
||||||
|
|
@ -2962,7 +2968,7 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(text) > 0 && column < parser.indent+1 && column != start_mark.column {
|
if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) {
|
||||||
// The comment at the different indentation is a foot of the
|
// The comment at the different indentation is a foot of the
|
||||||
// preceding data rather than a head of the upcoming one.
|
// preceding data rather than a head of the upcoming one.
|
||||||
parser.comments = append(parser.comments, yaml_comment_t{
|
parser.comments = append(parser.comments, yaml_comment_t{
|
||||||
|
|
@ -3013,6 +3019,10 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
|
||||||
peek = 0
|
peek = 0
|
||||||
column = 0
|
column = 0
|
||||||
line = parser.mark.line
|
line = parser.mark.line
|
||||||
|
next_indent = parser.indent
|
||||||
|
if next_indent < 0 {
|
||||||
|
next_indent = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(text) > 0 {
|
if len(text) > 0 {
|
||||||
|
|
|
||||||
|
|
@ -449,6 +449,11 @@ func (n *Node) ShortTag() string {
|
||||||
case ScalarNode:
|
case ScalarNode:
|
||||||
tag, _ := resolve("", n.Value)
|
tag, _ := resolve("", n.Value)
|
||||||
return tag
|
return tag
|
||||||
|
case 0:
|
||||||
|
// Special case to make the zero value convenient.
|
||||||
|
if n.IsZero() {
|
||||||
|
return nullTag
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ github.com/containers/buildah/pkg/overlay
|
||||||
github.com/containers/buildah/pkg/parse
|
github.com/containers/buildah/pkg/parse
|
||||||
github.com/containers/buildah/pkg/rusage
|
github.com/containers/buildah/pkg/rusage
|
||||||
github.com/containers/buildah/util
|
github.com/containers/buildah/util
|
||||||
# github.com/containers/common v0.40.2-0.20210630092122-7482cf851dcc
|
# github.com/containers/common v0.40.2-0.20210702074932-9d34b37ba77e
|
||||||
github.com/containers/common/libimage
|
github.com/containers/common/libimage
|
||||||
github.com/containers/common/libimage/manifests
|
github.com/containers/common/libimage/manifests
|
||||||
github.com/containers/common/pkg/apparmor
|
github.com/containers/common/pkg/apparmor
|
||||||
|
|
@ -115,6 +115,7 @@ github.com/containers/common/pkg/seccomp
|
||||||
github.com/containers/common/pkg/secrets
|
github.com/containers/common/pkg/secrets
|
||||||
github.com/containers/common/pkg/secrets/filedriver
|
github.com/containers/common/pkg/secrets/filedriver
|
||||||
github.com/containers/common/pkg/secrets/passdriver
|
github.com/containers/common/pkg/secrets/passdriver
|
||||||
|
github.com/containers/common/pkg/secrets/shelldriver
|
||||||
github.com/containers/common/pkg/signal
|
github.com/containers/common/pkg/signal
|
||||||
github.com/containers/common/pkg/subscriptions
|
github.com/containers/common/pkg/subscriptions
|
||||||
github.com/containers/common/pkg/supplemented
|
github.com/containers/common/pkg/supplemented
|
||||||
|
|
@ -426,6 +427,8 @@ github.com/matttproud/golang_protobuf_extensions/pbutil
|
||||||
github.com/miekg/pkcs11
|
github.com/miekg/pkcs11
|
||||||
# github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
|
# github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
|
||||||
github.com/mistifyio/go-zfs
|
github.com/mistifyio/go-zfs
|
||||||
|
# github.com/mitchellh/mapstructure v1.4.1
|
||||||
|
github.com/mitchellh/mapstructure
|
||||||
# github.com/moby/sys/mount v0.2.0
|
# github.com/moby/sys/mount v0.2.0
|
||||||
github.com/moby/sys/mount
|
github.com/moby/sys/mount
|
||||||
# github.com/moby/sys/mountinfo v0.4.1
|
# github.com/moby/sys/mountinfo v0.4.1
|
||||||
|
|
@ -570,7 +573,7 @@ github.com/seccomp/libseccomp-golang
|
||||||
# github.com/sirupsen/logrus v1.8.1
|
# github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/sirupsen/logrus
|
github.com/sirupsen/logrus
|
||||||
github.com/sirupsen/logrus/hooks/syslog
|
github.com/sirupsen/logrus/hooks/syslog
|
||||||
# github.com/spf13/cobra v1.1.3
|
# github.com/spf13/cobra v1.2.0
|
||||||
github.com/spf13/cobra
|
github.com/spf13/cobra
|
||||||
# github.com/spf13/pflag v1.0.5
|
# github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/pflag
|
github.com/spf13/pflag
|
||||||
|
|
@ -624,7 +627,7 @@ github.com/xeipuuv/gojsonschema
|
||||||
go.etcd.io/bbolt
|
go.etcd.io/bbolt
|
||||||
# go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1
|
# go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1
|
||||||
go.mozilla.org/pkcs7
|
go.mozilla.org/pkcs7
|
||||||
# go.opencensus.io v0.22.3
|
# go.opencensus.io v0.23.0
|
||||||
go.opencensus.io
|
go.opencensus.io
|
||||||
go.opencensus.io/internal
|
go.opencensus.io/internal
|
||||||
go.opencensus.io/trace
|
go.opencensus.io/trace
|
||||||
|
|
@ -664,7 +667,7 @@ golang.org/x/net/internal/socks
|
||||||
golang.org/x/net/internal/timeseries
|
golang.org/x/net/internal/timeseries
|
||||||
golang.org/x/net/proxy
|
golang.org/x/net/proxy
|
||||||
golang.org/x/net/trace
|
golang.org/x/net/trace
|
||||||
# golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
# golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/sync/semaphore
|
golang.org/x/sync/semaphore
|
||||||
# golang.org/x/sys v0.0.0-20210603125802-9665404d3644
|
# golang.org/x/sys v0.0.0-20210603125802-9665404d3644
|
||||||
golang.org/x/sys/cpu
|
golang.org/x/sys/cpu
|
||||||
|
|
@ -696,11 +699,11 @@ golang.org/x/text/secure/bidirule
|
||||||
golang.org/x/text/transform
|
golang.org/x/text/transform
|
||||||
golang.org/x/text/unicode/bidi
|
golang.org/x/text/unicode/bidi
|
||||||
golang.org/x/text/unicode/norm
|
golang.org/x/text/unicode/norm
|
||||||
# golang.org/x/tools v0.0.0-20210106214847-113979e3529a
|
# golang.org/x/tools v0.1.2
|
||||||
golang.org/x/tools/go/ast/inspector
|
golang.org/x/tools/go/ast/inspector
|
||||||
# google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a
|
# google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c
|
||||||
google.golang.org/genproto/googleapis/rpc/status
|
google.golang.org/genproto/googleapis/rpc/status
|
||||||
# google.golang.org/grpc v1.33.2
|
# google.golang.org/grpc v1.38.0
|
||||||
google.golang.org/grpc
|
google.golang.org/grpc
|
||||||
google.golang.org/grpc/attributes
|
google.golang.org/grpc/attributes
|
||||||
google.golang.org/grpc/backoff
|
google.golang.org/grpc/backoff
|
||||||
|
|
@ -727,12 +730,16 @@ google.golang.org/grpc/internal/grpclog
|
||||||
google.golang.org/grpc/internal/grpcrand
|
google.golang.org/grpc/internal/grpcrand
|
||||||
google.golang.org/grpc/internal/grpcsync
|
google.golang.org/grpc/internal/grpcsync
|
||||||
google.golang.org/grpc/internal/grpcutil
|
google.golang.org/grpc/internal/grpcutil
|
||||||
|
google.golang.org/grpc/internal/metadata
|
||||||
|
google.golang.org/grpc/internal/resolver
|
||||||
google.golang.org/grpc/internal/resolver/dns
|
google.golang.org/grpc/internal/resolver/dns
|
||||||
google.golang.org/grpc/internal/resolver/passthrough
|
google.golang.org/grpc/internal/resolver/passthrough
|
||||||
|
google.golang.org/grpc/internal/resolver/unix
|
||||||
google.golang.org/grpc/internal/serviceconfig
|
google.golang.org/grpc/internal/serviceconfig
|
||||||
google.golang.org/grpc/internal/status
|
google.golang.org/grpc/internal/status
|
||||||
google.golang.org/grpc/internal/syscall
|
google.golang.org/grpc/internal/syscall
|
||||||
google.golang.org/grpc/internal/transport
|
google.golang.org/grpc/internal/transport
|
||||||
|
google.golang.org/grpc/internal/transport/networktype
|
||||||
google.golang.org/grpc/keepalive
|
google.golang.org/grpc/keepalive
|
||||||
google.golang.org/grpc/metadata
|
google.golang.org/grpc/metadata
|
||||||
google.golang.org/grpc/peer
|
google.golang.org/grpc/peer
|
||||||
|
|
@ -784,7 +791,7 @@ gopkg.in/square/go-jose.v2/json
|
||||||
gopkg.in/tomb.v1
|
gopkg.in/tomb.v1
|
||||||
# gopkg.in/yaml.v2 v2.4.0
|
# gopkg.in/yaml.v2 v2.4.0
|
||||||
gopkg.in/yaml.v2
|
gopkg.in/yaml.v2
|
||||||
# gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
|
# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
gopkg.in/yaml.v3
|
gopkg.in/yaml.v3
|
||||||
# k8s.io/api v0.21.2
|
# k8s.io/api v0.21.2
|
||||||
k8s.io/api/apps/v1
|
k8s.io/api/apps/v1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue