diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..c70536b --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +golang 1.17.13 diff --git a/Makefile b/Makefile index b9a1695..d38c987 100644 --- a/Makefile +++ b/Makefile @@ -5,14 +5,16 @@ BIN_DARWIN = $(BIN)-darwin-$(ARCH) SOURCES := $(shell find . -iname '*.go') -.PHONY: test clean all +.PHONY: test clean all build-linux -all: build-darwin build-linux +all: build-darwin $(BIN_LINUX) build-darwin: $(SOURCES) GOARCH=$(ARCH) GOOS=darwin go build -o $(BIN_DARWIN) -build-linux: $(SOURCES) +build-linux: $(BIN_LINUX) + +$(BIN_LINUX): $(SOURCES) GOARCH=$(ARCH) GOOS=linux CGO_ENABLED=0 go build -o $(BIN_LINUX) test: $(SOURCES) @@ -22,7 +24,7 @@ bench: $(SOURCES) go test -run=XX -bench=. $(shell go list ./... | grep -v /vendor) docker: Dockerfile $(BIN_LINUX) - docker image build -t quay.io/uswitch/yggdrasil:devel . + docker image build -t registry.airship.rvu.cloud/cloud/yggdrasil:devel . clean: rm -rf bin/ diff --git a/README.md b/README.md index 4d9164c..4c6a376 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Yggdrasil Yggdrasil is an Envoy control plane that configures listeners and clusters based off Kubernetes ingresses from multiple Kube Clusters. This allows you to have an envoy cluster acting as a mutli-cluster loadbalancer for Kubernetes. This was something we needed as we wanted our apps to be highly available in the event of a cluster outage but did not want the solution to live inside of Kubernetes itself. -`Note:` Currently we support version 1.19.x of Envoy.
+`Note:` Currently we support versions 1.20.x to 1.26.x of Envoy.
`Note:` Yggdrasil now uses [Go modules](https://github.com/golang/go/wiki/Modules) to handle dependencies. ## Usage @@ -178,17 +178,18 @@ The Yggdrasil-specific metrics which are available from the API are: --ca string trustedCA --cert string certfile --config string config file +--config-dump Enable config dump endpoint at /configdump on the health-address HTTP server --debug Log at debug level --envoy-listener-ipv4-address string IPv4 address by the envoy proxy to accept incoming connections (default "0.0.0.0") --envoy-port uint32 port by the envoy proxy to accept incoming connections (default 10000) --health-address string yggdrasil health API listen address (default "0.0.0.0:8081") ---help help for yggdrasil +-h, --help help for yggdrasil --host-selection-retry-attempts int Number of host selection retry attempts. Set to value >=0 to enable (default -1) ---retry-on Default comma-separated list of retry policies (default 5xx) --http-ext-authz-allow-partial-message When this field is true, Envoy will buffer the message until max_request_bytes is reached (default true) --http-ext-authz-cluster string The name of the upstream gRPC cluster --http-ext-authz-failure-mode-allow Changes filters behaviour on errors (default true) --http-ext-authz-max-request-bytes uint32 Sets the maximum size of a message body that the filter will hold in memory (default 8192) +--http-ext-authz-pack-as-bytes When this field is true, Envoy will send the body as raw bytes. --http-ext-authz-timeout duration The timeout for the gRPC request. This is the timeout for a specific request. (default 200ms) --http-grpc-logger-cluster string The name of the upstream gRPC cluster --http-grpc-logger-name string Name of the access log @@ -200,6 +201,7 @@ The Yggdrasil-specific metrics which are available from the API are: --kube-config stringArray Path to kube config --max-ejection-percentage int32 maximal percentage of hosts ejected via outlier detection. Set to >=0 to activate outlier detection in envoy. (default -1) --node-name string envoy node name +--retry-on string default comma-separated list of retry policies (default "5xx") --upstream-healthcheck-healthy uint32 number of successful healthchecks before the backend is considered healthy (default 3) --upstream-healthcheck-interval duration duration of the upstream health check interval (default 10s) --upstream-healthcheck-timeout duration timeout of the upstream healthchecks (default 5s) diff --git a/cmd/root.go b/cmd/root.go index 0ad16c6..1743115 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -46,6 +46,7 @@ type config struct { UseRemoteAddress bool `json:"useRemoteAddress"` HttpExtAuthz envoy.HttpExtAuthz `json:"httpExtAuthz"` HttpGrpcLogger envoy.HttpGrpcLogger `json:"httpGrpcLogger"` + AccessLogger envoy.AccessLogger `json:"accessLogger"` } // Hasher returns node ID as an ID @@ -63,7 +64,7 @@ var rootCmd = &cobra.Command{ RunE: main, } -//Execute runs the function +// Execute runs the function func Execute() { if err := rootCmd.Execute(); err != nil { log.Fatal(err) @@ -83,6 +84,7 @@ func init() { rootCmd.PersistentFlags().StringSlice("ingress-classes", nil, "Ingress classes to watch") rootCmd.PersistentFlags().StringArrayVar(&kubeConfig, "kube-config", nil, "Path to kube config") rootCmd.PersistentFlags().Bool("debug", false, "Log at debug level") + rootCmd.PersistentFlags().Bool("config-dump", false, "Enable config dump endpoint at /configdump on the health-address HTTP server") rootCmd.PersistentFlags().Uint32("upstream-port", 443, "port used to connect to the upstream ingresses") rootCmd.PersistentFlags().String("envoy-listener-ipv4-address", "0.0.0.0", "IPv4 address by the envoy proxy to accept incoming connections") rootCmd.PersistentFlags().Uint32("envoy-port", 10000, "port by the envoy proxy to accept incoming connections") @@ -103,8 +105,11 @@ func init() { rootCmd.PersistentFlags().Duration("http-ext-authz-timeout", 200*time.Millisecond, "The timeout for the gRPC request. This is the timeout for a specific request.") rootCmd.PersistentFlags().Uint32("http-ext-authz-max-request-bytes", 8192, "Sets the maximum size of a message body that the filter will hold in memory") rootCmd.PersistentFlags().Bool("http-ext-authz-allow-partial-message", true, "When this field is true, Envoy will buffer the message until max_request_bytes is reached") + rootCmd.PersistentFlags().Bool("http-ext-authz-pack-as-bytes", false, "When this field is true, Envoy will send the body as raw bytes.") rootCmd.PersistentFlags().Bool("http-ext-authz-failure-mode-allow", true, "Changes filters behaviour on errors") + viper.BindPFlag("debug", rootCmd.PersistentFlags().Lookup("debug")) + viper.BindPFlag("configDump", rootCmd.PersistentFlags().Lookup("config-dump")) viper.BindPFlag("address", rootCmd.PersistentFlags().Lookup("address")) viper.BindPFlag("healthAddress", rootCmd.PersistentFlags().Lookup("health-address")) viper.BindPFlag("nodeName", rootCmd.PersistentFlags().Lookup("node-name")) @@ -132,6 +137,7 @@ func init() { viper.BindPFlag("httpExtAuthz.timeout", rootCmd.PersistentFlags().Lookup("http-ext-authz-timeout")) viper.BindPFlag("httpExtAuthz.maxRequestBytes", rootCmd.PersistentFlags().Lookup("http-ext-authz-max-request-bytes")) viper.BindPFlag("httpExtAuthz.allowPartialMessage", rootCmd.PersistentFlags().Lookup("http-ext-authz-allow-partial-message")) + viper.BindPFlag("httpExtAuthz.packAsBytes", rootCmd.PersistentFlags().Lookup("http-ext-authz-pack-as-bytes")) viper.BindPFlag("httpExtAuthz.FailureModeAllow", rootCmd.PersistentFlags().Lookup("http-ext-authz-failure-mode-allow")) } @@ -234,6 +240,7 @@ func main(*cobra.Command, []string) error { envoy.WithHttpGrpcLogger(c.HttpGrpcLogger), envoy.WithSyncSecrets(c.SyncSecrets), envoy.WithDefaultRetryOn(viper.GetString("retryOn")), + envoy.WithAccessLog(c.AccessLogger), ) snapshotter := envoy.NewSnapshotter(envoyCache, configurator, aggregator) @@ -241,7 +248,7 @@ func main(*cobra.Command, []string) error { go aggregator.Run() envoyServer := server.NewServer(ctx, envoyCache, &callbacks{}) - go runEnvoyServer(envoyServer, viper.GetString("address"), viper.GetString("healthAddress"), ctx.Done()) + go runEnvoyServer(envoyServer, snapshotter, viper.GetBool("configDump"), viper.GetString("address"), viper.GetString("healthAddress"), ctx.Done()) <-stopCh return nil diff --git a/cmd/server.go b/cmd/server.go index fdbf1d0..89df418 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "encoding/json" "fmt" "net" "net/http" @@ -16,6 +17,8 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" log "github.com/sirupsen/logrus" "google.golang.org/grpc" + + "github.com/uswitch/yggdrasil/pkg/envoy" ) type callbacks struct { @@ -39,7 +42,7 @@ func (c *callbacks) OnStreamClosed(int64) {} func (c *callbacks) OnStreamRequest(int64, *discovery.DiscoveryRequest) error { return nil } -func (c *callbacks) OnStreamResponse(int64, *discovery.DiscoveryRequest, *discovery.DiscoveryResponse) { +func (c *callbacks) OnStreamResponse(context.Context, int64, *discovery.DiscoveryRequest, *discovery.DiscoveryResponse) { } func (c *callbacks) OnFetchRequest(context.Context, *discovery.DiscoveryRequest) error { c.fetchReq++ @@ -49,7 +52,7 @@ func (c *callbacks) OnFetchResponse(*discovery.DiscoveryRequest, *discovery.Disc c.fetchResp++ } -func runEnvoyServer(envoyServer server.Server, address string, healthAddress string, stopCh <-chan struct{}) { +func runEnvoyServer(envoyServer server.Server, snapshotter *envoy.Snapshotter, enableConfigDump bool, address string, healthAddress string, stopCh <-chan struct{}) { grpcServer := grpc.NewServer( grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor), @@ -76,6 +79,9 @@ func runEnvoyServer(envoyServer server.Server, address string, healthAddress str healthMux.Handle("/metrics", promhttp.Handler()) healthMux.HandleFunc("/healthz", health) + if enableConfigDump { + healthMux.HandleFunc("/configdump", handleConfigDump(snapshotter)) + } go func() { if err = grpcServer.Serve(lis); err != nil { @@ -97,3 +103,34 @@ func runEnvoyServer(envoyServer server.Server, address string, healthAddress str func health(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) } + +type ConfigDumpError struct { + Error error + Message string +} + +func handleConfigDump(snapshotter *envoy.Snapshotter) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + snapshot, err := snapshotter.ConfigDump() + if err != nil { + respErr := ConfigDumpError{ + Error: err, + Message: "Unable to get current snapshot from snapshotter, see error for details.", + } + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(respErr) + return + } + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(snapshot) + } +} diff --git a/docs/ACCESSLOG.md b/docs/ACCESSLOG.md new file mode 100644 index 0000000..25540e2 --- /dev/null +++ b/docs/ACCESSLOG.md @@ -0,0 +1,37 @@ +# Access Log + +The Access log format is configurable via the Yggdrasil config file only. It is defined as a json object as follows: + +```json +{ + "accessLogger": { + "format": { + "bytes_received": "%BYTES_RECEIVED%", + "bytes_sent": "%BYTES_SENT%", + "downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%", + "downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%", + "duration": "%DURATION%", + "forwarded_for": "%REQ(X-FORWARDED-FOR)%", + "protocol": "%PROTOCOL%", + "request_id": "%REQ(X-REQUEST-ID)%", + "request_method": "%REQ(:METHOD)%", + "request_path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", + "response_code": "%RESPONSE_CODE%", + "response_flags": "%RESPONSE_FLAGS%", + "start_time": "%START_TIME(%s.%3f)%", + "upstream_cluster": "%UPSTREAM_CLUSTER%", + "upstream_host": "%UPSTREAM_HOST%", + "upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", + "upstream_service_time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%", + "user_agent": "%REQ(USER-AGENT)%" + } + } +} + +``` + +The config above would be the same as the default access logger config shipped with Yggdasil. Thus if no format is provided this will be the format used. + +[See Envoy docs for more on access log formats](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#config-access-log-default-format) + +The access log is written to `/var/log/envoy/access.log` which is not currently configurable. diff --git a/docs/GETTINGSTARTED.md b/docs/GETTINGSTARTED.md index 2341741..2c87891 100644 --- a/docs/GETTINGSTARTED.md +++ b/docs/GETTINGSTARTED.md @@ -138,7 +138,7 @@ By default, Yggdrasil will use an upstream ingress port of 443 (HTTPS), as we ar With the Yggdrasil container running, we can now configure an envoy node. Pull an envoy v1.10 docker image with the following command: ```console -$ docker pull envoyproxy/envoy:v1.19-latest +$ docker pull envoyproxy/envoy:v1.26-latest ``` Next, we will need to setup a minimal config file to create the admin listener for envoy, as well as pointing to our dynamic configuration provider - Yggdrasil: @@ -190,7 +190,7 @@ Where `` is the IP address of the Yggdrasil dock Run the envoy docker container with the following command, making sure to mount the minimal config file that you've created: ```console -$ docker run -e ENVOY_UID=0 -w /var/log/envoy/ -v /path/to/envoy.yaml:/etc/envoy/envoy.yaml -p 10000:10000 -d envoyproxy/envoy:v1.19-latest --service-node envoy-node --service-cluster envoy-node --config-path /etc/envoy/envoy.yaml +$ docker run -e ENVOY_UID=0 -w /var/log/envoy/ -v /path/to/envoy.yaml:/etc/envoy/envoy.yaml -p 10000:10000 -d envoyproxy/envoy:v1.26-latest --service-node envoy-node --service-cluster envoy-node --config-path /etc/envoy/envoy.yaml ``` The working directory for the container is set to `/var/log/envoy/` in order to create it at runtime, as Yggdrasil will configure envoy to write access logs to this directory. diff --git a/go.mod b/go.mod index 6d1269b..01f3071 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,15 @@ module github.com/uswitch/yggdrasil go 1.17 require ( - github.com/envoyproxy/go-control-plane v0.9.9 + github.com/envoyproxy/go-control-plane v0.10.3 github.com/golang/protobuf v1.5.2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/prometheus/client_golang v0.9.0 - github.com/sirupsen/logrus v1.1.1 + github.com/prometheus/client_golang v1.11.1 + github.com/sirupsen/logrus v1.6.0 github.com/spf13/cobra v0.0.3 github.com/spf13/viper v1.2.1 - google.golang.org/grpc v1.36.1 - google.golang.org/protobuf v1.27.1 + google.golang.org/grpc v1.45.0 + google.golang.org/protobuf v1.28.0 k8s.io/api v0.24.2 k8s.io/apimachinery v0.24.2 k8s.io/client-go v0.24.2 @@ -20,12 +20,13 @@ require ( require ( github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect - github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.8.0 // indirect - github.com/envoyproxy/protoc-gen-validate v0.5.1-0.20210316024357-9db8e779b461 // indirect + github.com/envoyproxy/protoc-gen-validate v0.6.7 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/go-logr/logr v1.2.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect @@ -33,14 +34,14 @@ require ( github.com/go-openapi/swag v0.19.14 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.5 // indirect + github.com/google/go-cmp v0.5.7 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.5 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/magiconair/properties v1.8.0 // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect @@ -50,21 +51,20 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml v1.2.0 // indirect github.com/prometheus/client_model v0.2.1-0.20200623203004-60555c9708c7 // indirect - github.com/prometheus/common v0.0.0-20170427095455-13ba4ddd0caa // indirect - github.com/prometheus/procfs v0.0.0-20170519190837-65c1f6f8f0fc // indirect - github.com/spf13/afero v1.3.4 // indirect + github.com/prometheus/common v0.26.0 // indirect + github.com/prometheus/procfs v0.6.0 // indirect + github.com/spf13/afero v1.6.0 // indirect github.com/spf13/cast v1.3.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect - golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1 // indirect + google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/go.sum b/go.sum index 49b7e21..10c9f25 100644 --- a/go.sum +++ b/go.sum @@ -47,18 +47,30 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= 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/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -66,9 +78,13 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk 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/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158 h1:CevA8fI91PAnP8vpnXuB8ZYAZ5wqY86nAbxfgK8tWO4= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc h1:PYXxkRUBGUMa5xgMVMDl62vEklZvKpVaxQeN9ie7Hfk= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= @@ -85,11 +101,13 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m 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 h1:vQLjymTobffN2R0F8eTqw6q7iozfRO5Z0m+/4Vw+/uA= -github.com/envoyproxy/go-control-plane v0.9.9/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.3 h1:xdCVXxEe0Y3FQith+0cj2irwZudqGYvecuLB1HtdexY= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.5.1-0.20210316024357-9db8e779b461 h1:wxPSeXm7IFrHnzX3nQ5LdN0fNS2sSg6T/ESs6fNj3gw= -github.com/envoyproxy/protoc-gen-validate v0.5.1-0.20210316024357-9db8e779b461/go.mod h1:xL5IroIBOR+aTp0IZk48epGwBV3+LcuaosPL0pr0hE0= +github.com/envoyproxy/protoc-gen-validate v0.6.7 h1:qcZcULcd/abmQg6dwigimCNEyi4gg31M/xaciQlDml8= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -101,6 +119,12 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= @@ -114,9 +138,12 @@ github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/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= @@ -162,8 +189,10 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -192,12 +221,13 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= 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 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= @@ -206,24 +236,30 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 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.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= +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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -239,12 +275,15 @@ github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0Gq github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/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.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -262,29 +301,44 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.0 h1:tXuTFVHC03mW0D+Ua1Q2d1EAVqLTuggX50V0VLICCzY= -github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.1-0.20200623203004-60555c9708c7 h1:NkLt0ne/zifxULGse6IDsHU45hKk3w6lIVs8yFSVzKU= github.com/prometheus/client_model v0.2.1-0.20200623203004-60555c9708c7/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20170427095455-13ba4ddd0caa h1:WBOqSBZzK9pqPXiewLT2aL9evdTCy4hUefz0h3iJGGI= -github.com/prometheus/common v0.0.0-20170427095455-13ba4ddd0caa/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/procfs v0.0.0-20170519190837-65c1f6f8f0fc h1:eEx6/InsHC/w5bo5ADfs4u7uf7NXgmDDui12UF205Ag= -github.com/prometheus/procfs v0.0.0-20170519190837-65c1f6f8f0fc/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 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/sirupsen/logrus v1.1.1 h1:VzGj7lhU7KEB9e9gMpAV/v5XT2NVSvLJhJLCWbnkgXg= -github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +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.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc= -github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -300,18 +354,21 @@ github.com/spf13/viper v1.2.1 h1:bIcUwXqLseLF3BDAZduuNfekWG87ibtFxi59Bq+oI9M= github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= 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.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/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -320,6 +377,7 @@ 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/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -328,7 +386,7 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U 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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/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= @@ -353,6 +411,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu 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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -364,9 +423,12 @@ 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/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -374,6 +436,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/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= @@ -401,9 +464,12 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v 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-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -428,13 +494,16 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-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-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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -446,6 +515,7 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/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-20200106162015-b016eb3dc98e/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= @@ -459,6 +529,8 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-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= @@ -466,6 +538,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210124154548-22da62e12c0c/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= @@ -473,13 +546,19 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -488,8 +567,9 @@ 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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -532,7 +612,6 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/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-20200522201501-cb1345f3a375/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= @@ -546,6 +625,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f 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.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -620,8 +700,10 @@ google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6D 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 h1:E7wSQBXkH3T3diucK+9Z1kjn4+/9tNG7lZLr75oOhh8= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7 h1:HOL66YCI20JvN2hVk6o2YIp9i/3RvzVUz82PqNr7fXw= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -640,8 +722,11 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv 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 h1:cmUfbeGKnz9+2DD/UYsMQXeqbHZqZDs4eQwW0sFOpBY= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= 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= @@ -654,8 +739,10 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -671,6 +758,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/pkg/envoy/boilerplate.go b/pkg/envoy/boilerplate.go index 7c4bcbc..50041ce 100644 --- a/pkg/envoy/boilerplate.go +++ b/pkg/envoy/boilerplate.go @@ -15,13 +15,15 @@ import ( gal "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/grpc/v3" eauthz "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" hcfg "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/health_check/v3" + tlsInspector "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/tls_inspector/v3" hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + previousHosts "github.com/envoyproxy/go-control-plane/envoy/extensions/retry/host/previous_hosts/v3" auth "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - util "github.com/envoyproxy/go-control-plane/pkg/conversion" - types "github.com/golang/protobuf/ptypes" + matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" any "github.com/golang/protobuf/ptypes/any" "github.com/golang/protobuf/ptypes/duration" "github.com/golang/protobuf/ptypes/wrappers" + "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/wrapperspb" @@ -30,35 +32,30 @@ import ( var ( jsonFormat *structpb.Struct allowedRetryOns map[string]bool -) -func init() { - format := map[string]interface{}{ - "start_time": "%START_TIME(%s.%3f)%", + DefaultAccessLogFormat = map[string]interface{}{ "bytes_received": "%BYTES_RECEIVED%", - "protocol": "%PROTOCOL%", - "response_code": "%RESPONSE_CODE%", "bytes_sent": "%BYTES_SENT%", + "downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%", + "downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%", "duration": "%DURATION%", + "forwarded_for": "%REQ(X-FORWARDED-FOR)%", + "protocol": "%PROTOCOL%", + "request_id": "%REQ(X-REQUEST-ID)%", + "request_method": "%REQ(:METHOD)%", + "request_path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", + "response_code": "%RESPONSE_CODE%", "response_flags": "%RESPONSE_FLAGS%", - "upstream_host": "%UPSTREAM_HOST%", + "start_time": "%START_TIME(%s.%3f)%", "upstream_cluster": "%UPSTREAM_CLUSTER%", + "upstream_host": "%UPSTREAM_HOST%", "upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", - "downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%", - "downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%", - "request_method": "%REQ(:METHOD)%", - "request_path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", "upstream_service_time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%", - "forwarded_for": "%REQ(X-FORWARDED-FOR)%", "user_agent": "%REQ(USER-AGENT)%", - "request_id": "%REQ(X-REQUEST-ID)%", - } - b, err := structpb.NewValue(format) - if err != nil { - log.Fatal(err) } - jsonFormat = b.GetStructValue() +) +func init() { allowedRetryOns = map[string]bool{ "5xx": true, "gateway-error": true, @@ -73,7 +70,7 @@ func init() { } } -func makeVirtualHost(vhost *virtualHost, reselectionAttempts int64, defaultRetryOn string) *route.VirtualHost { +func makeVirtualHost(vhost *virtualHost, reselectionAttempts int64, defaultRetryOn string) (*route.VirtualHost, error) { retryOn := vhost.RetryOn if retryOn == "" { retryOn = defaultRetryOn @@ -92,10 +89,18 @@ func makeVirtualHost(vhost *virtualHost, reselectionAttempts int64, defaultRetry }, } + hosts := &previousHosts.PreviousHostsPredicate{} + + anyHosts, err := anypb.New(hosts) + if err != nil { + return &route.VirtualHost{}, fmt.Errorf("failed to marshal hosts config struct to typed struct: %s", err) + } + if reselectionAttempts >= 0 { action.Route.RetryPolicy.RetryHostPredicate = []*route.RetryPolicy_RetryHostPredicate{ { - Name: "envoy.retry_host_predicates.previous_hosts", + Name: "envoy.retry_host_predicates.previous_hosts", + ConfigType: &route.RetryPolicy_RetryHostPredicate_TypedConfig{TypedConfig: anyHosts}, }, } action.Route.RetryPolicy.HostSelectionRetryMaxAttempts = reselectionAttempts @@ -114,7 +119,7 @@ func makeVirtualHost(vhost *virtualHost, reselectionAttempts int64, defaultRetry }, }, } - return &virtualHost + return &virtualHost, nil } func makeHealthConfig() *hcfg.HealthCheck { @@ -123,8 +128,10 @@ func makeHealthConfig() *hcfg.HealthCheck { Headers: []*route.HeaderMatcher{ { Name: ":path", - HeaderMatchSpecifier: &route.HeaderMatcher_ExactMatch{ - ExactMatch: "/yggdrasil/status", + HeaderMatchSpecifier: &route.HeaderMatcher_StringMatch{ + StringMatch: &matcherv3.StringMatcher{ + MatchPattern: &matcherv3.StringMatcher_Exact{Exact: "/yggdrasil/status"}, + }, }, }, }, @@ -147,6 +154,7 @@ func makeExtAuthzConfig(cfg HttpExtAuthz) *eauthz.ExtAuthz { WithRequestBody: &eauthz.BufferSettings{ MaxRequestBytes: cfg.MaxRequestBytes, AllowPartialMessage: cfg.AllowPartialMessage, + PackAsBytes: cfg.PackAsBytes, }, FailureModeAllow: cfg.FailureModeAllow, } @@ -166,29 +174,41 @@ func makeGrpcLoggerConfig(cfg HttpGrpcLogger) *gal.HttpGrpcAccessLogConfig { }, TransportApiVersion: core.ApiVersion_V3, }, - AdditionalRequestHeadersToLog: cfg.AdditionalRequestHeaders, - AdditionalResponseHeadersToLog: cfg.AdditionalResponseHeaders, + AdditionalRequestHeadersToLog: cfg.RequestHeaders, + AdditionalResponseHeadersToLog: cfg.ResponseHeaders, } } -func (c *KubernetesConfigurator) makeConnectionManager(virtualHosts []*route.VirtualHost) *hcm.HttpConnectionManager { - // Access Logs - accessLogConfig, err := util.MessageToStruct( - &eal.FileAccessLog{ - Path: "/var/log/envoy/access.log", - AccessLogFormat: &eal.FileAccessLog_LogFormat{ - LogFormat: &core.SubstitutionFormatString{ - Format: &core.SubstitutionFormatString_JsonFormat{ - JsonFormat: jsonFormat, - }, +func makeFileAccessLog(cfg AccessLogger) *eal.FileAccessLog { + format := DefaultAccessLogFormat + if len(cfg.Format) > 0 { + format = cfg.Format + } + + b, err := structpb.NewValue(format) + if err != nil { + log.Fatal(err) + } + jsonFormat = b.GetStructValue() + + accessLogConfig := &eal.FileAccessLog{ + Path: "/var/log/envoy/access.log", + AccessLogFormat: &eal.FileAccessLog_LogFormat{ + LogFormat: &core.SubstitutionFormatString{ + Format: &core.SubstitutionFormatString_JsonFormat{ + JsonFormat: jsonFormat, }, }, }, - ) - if err != nil { - log.Fatalf("failed to convert access log proto message to struct: %s", err) } - anyAccessLogConfig, err := types.MarshalAny(accessLogConfig) + + return accessLogConfig +} + +func (c *KubernetesConfigurator) makeConnectionManager(virtualHosts []*route.VirtualHost) (*hcm.HttpConnectionManager, error) { + // Access Logs + accessLogConfig := makeFileAccessLog(c.accessLogger) + anyAccessLogConfig, err := anypb.New(accessLogConfig) if err != nil { log.Fatalf("failed to marshal access log config struct to typed struct: %s", err) } @@ -201,11 +221,7 @@ func (c *KubernetesConfigurator) makeConnectionManager(virtualHosts []*route.Vir } if c.httpGrpcLogger.Cluster != "" { - grpcLoggerConfig, err := util.MessageToStruct(makeGrpcLoggerConfig(c.httpGrpcLogger)) - if err != nil { - log.Fatalf("failed to convert healthcheck proto message to struct: %s", err) - } - anyGrpcLoggerConfig, err := types.MarshalAny(grpcLoggerConfig) + anyGrpcLoggerConfig, err := anypb.New(makeGrpcLoggerConfig(c.httpGrpcLogger)) if err != nil { log.Fatalf("failed to marshal healthcheck config struct to typed struct: %s", err) } @@ -218,11 +234,7 @@ func (c *KubernetesConfigurator) makeConnectionManager(virtualHosts []*route.Vir // HTTP Filters filterBuilder := &httpFilterBuilder{} - healthConfig, err := util.MessageToStruct(makeHealthConfig()) - if err != nil { - log.Fatalf("failed to convert healthcheck proto message to struct: %s", err) - } - anyHealthConfig, err := types.MarshalAny(healthConfig) + anyHealthConfig, err := anypb.New(makeHealthConfig()) if err != nil { log.Fatalf("failed to marshal healthcheck config struct to typed struct: %s", err) } @@ -233,11 +245,7 @@ func (c *KubernetesConfigurator) makeConnectionManager(virtualHosts []*route.Vir }) if c.httpExtAuthz.Cluster != "" { - extAuthzConfig, err := util.MessageToStruct(makeExtAuthzConfig(c.httpExtAuthz)) - if err != nil { - log.Fatalf("failed to convert extAuthz proto message to struct: %s", err) - } - anyExtAuthzConfig, err := types.MarshalAny(extAuthzConfig) + anyExtAuthzConfig, err := anypb.New(makeExtAuthzConfig(c.httpExtAuthz)) if err != nil { log.Fatalf("failed to marshal extAuthz config struct to typed struct: %s", err) } @@ -248,10 +256,15 @@ func (c *KubernetesConfigurator) makeConnectionManager(virtualHosts []*route.Vir }) } + filter, err := filterBuilder.Filters() + if err != nil { + return &hcm.HttpConnectionManager{}, err + } + return &hcm.HttpConnectionManager{ CodecType: hcm.HttpConnectionManager_AUTO, StatPrefix: "ingress_http", - HttpFilters: filterBuilder.Filters(), + HttpFilters: filter, UpgradeConfigs: []*hcm.HttpConnectionManager_UpgradeConfig{ { UpgradeType: "websocket", @@ -266,16 +279,15 @@ func (c *KubernetesConfigurator) makeConnectionManager(virtualHosts []*route.Vir Tracing: &hcm.HttpConnectionManager_Tracing{}, AccessLog: accessLoggers, UseRemoteAddress: &wrapperspb.BoolValue{Value: c.useRemoteAddress}, - } + }, nil } func (c *KubernetesConfigurator) makeFilterChain(certificate Certificate, virtualHosts []*route.VirtualHost) (listener.FilterChain, error) { - httpConnectionManager := c.makeConnectionManager(virtualHosts) - httpConfig, err := util.MessageToStruct(httpConnectionManager) + httpConnectionManager, err := c.makeConnectionManager(virtualHosts) if err != nil { - return listener.FilterChain{}, fmt.Errorf("failed to convert virtualHost to envoy control plane struct: %s", err) + return listener.FilterChain{}, fmt.Errorf("failed to get httpConnectionManager: %s", err) } - anyHttpConfig, err := types.MarshalAny(httpConfig) + anyHttpConfig, err := anypb.New(httpConnectionManager) if err != nil { return listener.FilterChain{}, fmt.Errorf("failed to marshal HTTP config struct to typed struct: %s", err) } @@ -294,7 +306,7 @@ func (c *KubernetesConfigurator) makeFilterChain(certificate Certificate, virtua }, } - anyTls, err := types.MarshalAny(tls) + anyTls, err := anypb.New(tls) if err != nil { return listener.FilterChain{}, fmt.Errorf("failed to marshal TLS config struct to typed struct: %s", err) } @@ -328,8 +340,15 @@ func (c *KubernetesConfigurator) makeFilterChain(certificate Certificate, virtua }, nil } -func makeListener(filterChains []*listener.FilterChain, envoyListenerIpv4Address string, envoyListenPort uint32) *listener.Listener { +func makeListener(filterChains []*listener.FilterChain, envoyListenerIpv4Address string, envoyListenPort uint32) (*listener.Listener, error) { + tlsInspectorConfig, err := anypb.New(&tlsInspector.TlsInspector{}) + if err != nil { + return &listener.Listener{}, fmt.Errorf("failed to marshal tls_inspector config struct to typed struct: %s", err) + } + if err != nil { + return &listener.Listener{}, fmt.Errorf("failed to marshal TLS config struct to typed struct: %s", err) + } listener := listener.Listener{ Name: "listener_0", Address: &core.Address{ @@ -343,14 +362,17 @@ func makeListener(filterChains []*listener.FilterChain, envoyListenerIpv4Address }, }, ListenerFilters: []*listener.ListenerFilter{ - {Name: "envoy.filters.listener.tls_inspector"}, + { + Name: "envoy.filters.listener.tls_inspector", + ConfigType: &listener.ListenerFilter_TypedConfig{TypedConfig: tlsInspectorConfig}, + }, }, FilterChains: filterChains, // Setting the TrafficDirection here for tracing TrafficDirection: core.TrafficDirection_OUTBOUND, } - return &listener + return &listener, nil } func makeAddresses(addresses []string, upstreamPort uint32) []*core.Address { @@ -416,7 +438,7 @@ func makeCluster(c cluster, ca string, healthCfg UpstreamHealthCheck, outlierPer var anyTls *any.Any if tls != nil { - anyTls, err = types.MarshalAny(tls) + anyTls, err = anypb.New(tls) if err != nil { log.Printf("Error marhsalling cluster TLS config: %s", err) } diff --git a/pkg/envoy/boilerplate_test.go b/pkg/envoy/boilerplate_test.go index 93b8705..42779e7 100644 --- a/pkg/envoy/boilerplate_test.go +++ b/pkg/envoy/boilerplate_test.go @@ -2,10 +2,12 @@ package envoy import ( "fmt" + "reflect" "testing" "time" core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + eal "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/file/v3" "github.com/golang/protobuf/ptypes/duration" ) @@ -56,6 +58,48 @@ func TestMakeHealthChecksValidPath(t *testing.T) { } +type accessLoggerTestCase struct { + name string + format map[string]interface{} + custom bool +} + +func TestAccessLoggerConfig(t *testing.T) { + testCases := []accessLoggerTestCase{ + {name: "default log format", format: DefaultAccessLogFormat, custom: false}, + {name: "custom log format", format: map[string]interface{}{"a-key": "a-format-specifier"}, custom: true}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cfg := AccessLogger{} + if tc.custom { + cfg.Format = tc.format + } + + fileAccessLog := makeFileAccessLog(cfg) + if fileAccessLog.Path != "/var/log/envoy/access.log" { + t.Errorf("Expected access log to use default path but was, %s", fileAccessLog.Path) + } + + alf, ok := fileAccessLog.AccessLogFormat.(*eal.FileAccessLog_LogFormat) + if !ok { + t.Fatalf("File Access Log Format had incorrect type, should be FileAccessLog_LogFormat") + } + + lf, ok := alf.LogFormat.Format.(*core.SubstitutionFormatString_JsonFormat) + if !ok { + t.Fatalf("LogFormat had incorrect type, should be SubstitutionFormatString_JsonFormat") + } + + format := lf.JsonFormat.AsMap() + if !reflect.DeepEqual(format, tc.format) { + t.Errorf("Log format map should match configuration") + } + }) + } +} + func mustParseDuration(dur string) time.Duration { d, err := time.ParseDuration(dur) if err != nil { diff --git a/pkg/envoy/config_dump.go b/pkg/envoy/config_dump.go new file mode 100644 index 0000000..3c18c02 --- /dev/null +++ b/pkg/envoy/config_dump.go @@ -0,0 +1,26 @@ +package envoy + +import ( + types "github.com/envoyproxy/go-control-plane/pkg/cache/types" + resource "github.com/envoyproxy/go-control-plane/pkg/resource/v3" +) + +type EnvoySnapshot struct { + Listeners map[string]types.Resource + Clusters map[string]types.Resource +} + +func (s *Snapshotter) ConfigDump() (EnvoySnapshot, error) { + snapshot, err := s.CurrentSnapshot() + if err != nil { + return EnvoySnapshot{}, err + } + + listeners := snapshot.GetResources(resource.ListenerType) + clusters := snapshot.GetResources(resource.ClusterType) + + return EnvoySnapshot{ + Listeners: listeners, + Clusters: clusters, + }, nil +} diff --git a/pkg/envoy/configurator.go b/pkg/envoy/configurator.go index 383de0c..fc13a9a 100644 --- a/pkg/envoy/configurator.go +++ b/pkg/envoy/configurator.go @@ -11,7 +11,6 @@ import ( route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" tcache "github.com/envoyproxy/go-control-plane/pkg/cache/types" cache "github.com/envoyproxy/go-control-plane/pkg/cache/v3" - util "github.com/envoyproxy/go-control-plane/pkg/conversion" "github.com/sirupsen/logrus" "github.com/uswitch/yggdrasil/pkg/k8s" "google.golang.org/protobuf/types/known/anypb" @@ -36,18 +35,23 @@ type HttpExtAuthz struct { Timeout time.Duration `json:"timeout"` MaxRequestBytes uint32 `json:"maxRequestBytes"` AllowPartialMessage bool `json:"allowPartialMessage"` + PackAsBytes bool `json:"packAsBytes"` FailureModeAllow bool `json:"FailureModeAllow"` } type HttpGrpcLogger struct { - Name string `json:"name"` - Cluster string `json:"cluster"` - Timeout time.Duration `json:"timeout"` - AdditionalRequestHeaders []string `json:"additionalRequestHeaders"` - AdditionalResponseHeaders []string `json:"additionalResponseHeaders"` + Name string `json:"name"` + Cluster string `json:"cluster"` + Timeout time.Duration `json:"timeout"` + RequestHeaders []string `json:"requestHeaders"` + ResponseHeaders []string `json:"responseHeaders"` } -//KubernetesConfigurator takes a given Ingress Class and lister to find only ingresses of that class +type AccessLogger struct { + Format map[string]interface{} `json:"format"` +} + +// KubernetesConfigurator takes a given Ingress Class and lister to find only ingresses of that class type KubernetesConfigurator struct { ingressClasses []string nodeID string @@ -63,6 +67,7 @@ type KubernetesConfigurator struct { useRemoteAddress bool httpExtAuthz HttpExtAuthz httpGrpcLogger HttpGrpcLogger + accessLogger AccessLogger defaultRetryOn string previousConfig *envoyConfiguration @@ -71,7 +76,7 @@ type KubernetesConfigurator struct { sync.Mutex } -//NewKubernetesConfigurator returns a Kubernetes configurator given a lister and ingress class +// NewKubernetesConfigurator returns a Kubernetes configurator given a lister and ingress class func NewKubernetesConfigurator(nodeID string, certificates []Certificate, ca string, ingressClasses []string, options ...option) *KubernetesConfigurator { c := &KubernetesConfigurator{ingressClasses: ingressClasses, nodeID: nodeID, certificates: certificates, trustCA: ca} for _, opt := range options { @@ -81,7 +86,7 @@ func NewKubernetesConfigurator(nodeID string, certificates []Certificate, ca str } //Generate creates a new snapshot -func (c *KubernetesConfigurator) Generate(ingresses []*k8s.Ingress, secrets []*v1.Secret) cache.Snapshot { +func (c *KubernetesConfigurator) Generate(ingresses []*k8s.Ingress, secrets []*v1.Secret) (cache.Snapshot, error) { c.Lock() defer c.Unlock() @@ -91,7 +96,10 @@ func (c *KubernetesConfigurator) Generate(ingresses []*k8s.Ingress, secrets []*v vmatch, cmatch := config.equals(c.previousConfig) clusters := c.generateClusters(config) - listeners := c.generateListeners(config) + listeners, err := c.generateListeners(config) + if err != nil { + return cache.Snapshot{}, err + } if !vmatch { c.listenerVersion = time.Now().String() @@ -107,10 +115,10 @@ func (c *KubernetesConfigurator) Generate(ingresses []*k8s.Ingress, secrets []*v snap := cache.Snapshot{} snap.Resources[tcache.Cluster] = cache.NewResources(c.clusterVersion, []tcache.Resource(clusters)) snap.Resources[tcache.Listener] = cache.NewResources(c.listenerVersion, []tcache.Resource(listeners)) - return snap + return snap, nil } -//NodeID returns the NodeID +// NodeID returns the NodeID func (c *KubernetesConfigurator) NodeID() string { return c.nodeID @@ -153,25 +161,33 @@ func (c *KubernetesConfigurator) matchCertificateIndices(virtualHost *virtualHos return []int{}, errNoCertificateMatch } -func (c *KubernetesConfigurator) generateListeners(config *envoyConfiguration) []tcache.Resource { +func (c *KubernetesConfigurator) generateListeners(config *envoyConfiguration) ([]tcache.Resource, error) { var filterChains []*listener.FilterChain + var err error if c.syncSecrets { - filterChains = c.generateDynamicTLSFilterChains(config) + filterChains, err = c.generateDynamicTLSFilterChains(config) } else if len(c.certificates) > 0 { - filterChains = c.generateTLSFilterChains(config) + filterChains, err = c.generateTLSFilterChains(config) } else { - filterChains = c.generateHTTPFilterChain(config) + filterChains, err = c.generateHTTPFilterChain(config) + } + if err != nil { + return []tcache.Resource{}, err } - return []tcache.Resource{makeListener(filterChains, c.envoyListenerIpv4Address, c.envoyListenPort)} + listener, err := makeListener(filterChains, c.envoyListenerIpv4Address, c.envoyListenPort) + return []tcache.Resource{listener}, err } -func (c *KubernetesConfigurator) generateDynamicTLSFilterChains(config *envoyConfiguration) []*listener.FilterChain { +func (c *KubernetesConfigurator) generateDynamicTLSFilterChains(config *envoyConfiguration) ([]*listener.FilterChain, error) { filterChains := []*listener.FilterChain{} allVhosts := []*route.VirtualHost{} for _, virtualHost := range config.VirtualHosts { - envoyVhost := makeVirtualHost(virtualHost, c.hostSelectionRetryAttempts, c.defaultRetryOn) + envoyVhost, err := makeVirtualHost(virtualHost, c.hostSelectionRetryAttempts, c.defaultRetryOn) + if err != nil { + return nil, err + } allVhosts = append(allVhosts, envoyVhost) if virtualHost.TlsCert == "" || virtualHost.TlsKey == "" { @@ -207,21 +223,24 @@ func (c *KubernetesConfigurator) generateDynamicTLSFilterChains(config *envoyCon } } - return filterChains + return filterChains, nil } -func (c *KubernetesConfigurator) generateHTTPFilterChain(config *envoyConfiguration) []*listener.FilterChain { +func (c *KubernetesConfigurator) generateHTTPFilterChain(config *envoyConfiguration) ([]*listener.FilterChain, error) { virtualHosts := []*route.VirtualHost{} for _, virtualHost := range config.VirtualHosts { - virtualHosts = append(virtualHosts, makeVirtualHost(virtualHost, c.hostSelectionRetryAttempts, c.defaultRetryOn)) + vhost, err := makeVirtualHost(virtualHost, c.hostSelectionRetryAttempts, c.defaultRetryOn) + if err != nil { + return nil, err + } + virtualHosts = append(virtualHosts, vhost) } - httpConnectionManager := c.makeConnectionManager(virtualHosts) - httpConfig, err := util.MessageToStruct(httpConnectionManager) + httpConnectionManager, err := c.makeConnectionManager(virtualHosts) if err != nil { - log.Fatalf("failed to convert virtualHost to envoy control plane struct: %s", err) + return nil, err } - anyHttpConfig, err := anypb.New(httpConfig) + anyHttpConfig, err := anypb.New(httpConnectionManager) if err != nil { log.Fatalf("failed to marshal HTTP config struct to typed struct: %s", err) } @@ -234,10 +253,10 @@ func (c *KubernetesConfigurator) generateHTTPFilterChain(config *envoyConfigurat }, }, }, - } + }, nil } -func (c *KubernetesConfigurator) generateTLSFilterChains(config *envoyConfiguration) []*listener.FilterChain { +func (c *KubernetesConfigurator) generateTLSFilterChains(config *envoyConfiguration) ([]*listener.FilterChain, error) { virtualHostsForCertificates := make([][]*route.VirtualHost, len(c.certificates)) for _, virtualHost := range config.VirtualHosts { @@ -246,7 +265,11 @@ func (c *KubernetesConfigurator) generateTLSFilterChains(config *envoyConfigurat log.Printf("error matching certificate for '%s': %v", virtualHost.Host, err) } else { for _, idx := range certificateIndicies { - virtualHostsForCertificates[idx] = append(virtualHostsForCertificates[idx], makeVirtualHost(virtualHost, c.hostSelectionRetryAttempts, c.defaultRetryOn)) + vhost, err := makeVirtualHost(virtualHost, c.hostSelectionRetryAttempts, c.defaultRetryOn) + if err != nil { + return nil, err + } + virtualHostsForCertificates[idx] = append(virtualHostsForCertificates[idx], vhost) } } } @@ -266,7 +289,7 @@ func (c *KubernetesConfigurator) generateTLSFilterChains(config *envoyConfigurat filterChains = append(filterChains, &filterChain) } - return filterChains + return filterChains, nil } func (c *KubernetesConfigurator) generateClusters(config *envoyConfiguration) []tcache.Resource { diff --git a/pkg/envoy/configurator_test.go b/pkg/envoy/configurator_test.go index fcc952c..b50d91b 100644 --- a/pkg/envoy/configurator_test.go +++ b/pkg/envoy/configurator_test.go @@ -4,32 +4,21 @@ import ( "testing" "time" - core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" tcache "github.com/envoyproxy/go-control-plane/pkg/cache/types" - util "github.com/envoyproxy/go-control-plane/pkg/conversion" - "github.com/golang/protobuf/ptypes" "github.com/uswitch/yggdrasil/pkg/k8s" v1 "k8s.io/api/core/v1" ) func assertNumberOfVirtualHosts(t *testing.T, filterChain *listener.FilterChain, expected int) { - var connManager hcm.HttpConnectionManager - var dynamicAny ptypes.DynamicAny - - err := ptypes.UnmarshalAny(filterChain.Filters[0].GetTypedConfig(), &dynamicAny) + filter, err := filterChain.Filters[0].GetTypedConfig().UnmarshalNew() if err != nil { t.Fatal(err) } - structMessage, err := util.MessageToStruct(dynamicAny.Message) - if err != nil { - t.Fatal(err) - } - - err = util.StructToMessage(structMessage, &connManager) - if err != nil { + connManager, ok := filter.(*hcm.HttpConnectionManager) + if !ok { t.Fatal(err) } @@ -42,21 +31,6 @@ func assertNumberOfVirtualHosts(t *testing.T, filterChain *listener.FilterChain, } -func assertTlsCertificate(t *testing.T, filterChain listener.FilterChain, expectedCert, expectedKey string) { - certificate := filterChain.HiddenEnvoyDeprecatedTlsContext.CommonTlsContext.TlsCertificates[0] - - certFile := certificate.CertificateChain.Specifier.(*core.DataSource_InlineString) - keyFile := certificate.PrivateKey.Specifier.(*core.DataSource_InlineString) - - if certFile.InlineString != expectedCert { - t.Fatalf("certficiate chain filename: '%s' expected '%s'", certFile.InlineString, expectedCert) - } - - if keyFile.InlineString != expectedKey { - t.Fatalf("private key filename: '%s' expected '%s'", keyFile.InlineString, expectedKey) - } -} - func assertServerNames(t *testing.T, filterChain *listener.FilterChain, expectedServerNames []string) { serverNames := filterChain.FilterChainMatch.ServerNames @@ -80,7 +54,7 @@ func TestGenerate(t *testing.T) { {Hosts: []string{"*"}, Cert: "b", Key: "c"}, }, "d", []string{"bar"}) - snapshot := configurator.Generate(ingresses, []*v1.Secret{}) + snapshot, _ := configurator.Generate(ingresses, []*v1.Secret{}) if len(snapshot.Resources[tcache.Listener].Items) != 1 { t.Fatalf("Num listeners: %d", len(snapshot.Resources[tcache.Listener].Items)) @@ -101,7 +75,11 @@ func TestGenerateMultipleCerts(t *testing.T) { {Hosts: []string{"*.internal.api.co.uk"}, Cert: "couk", Key: "couk"}, }, "d", []string{"bar"}) - snapshot := configurator.Generate(ingresses, []*v1.Secret{}) + snapshot, err := configurator.Generate(ingresses, []*v1.Secret{}) + if err != nil { + t.Fatalf("Error generating snapshot %v", err) + } + listener := snapshot.Resources[tcache.Listener].Items["listener_0"].Resource.(*listener.Listener) if len(listener.FilterChains) != 2 { @@ -122,7 +100,11 @@ func TestGenerateMultipleHosts(t *testing.T) { {Hosts: []string{"*.internal.api.com", "*.internal.api.co.uk"}, Cert: "com", Key: "com"}, }, "d", []string{"bar"}) - snapshot := configurator.Generate(ingresses, []*v1.Secret{}) + snapshot, err := configurator.Generate(ingresses, []*v1.Secret{}) + if err != nil { + t.Fatalf("Error generating snapshot %v", err) + } + listener := snapshot.Resources[tcache.Listener].Items["listener_0"].Resource.(*listener.Listener) if len(listener.FilterChains) != 1 { @@ -143,7 +125,11 @@ func TestGenerateNoMatchingCert(t *testing.T) { {Hosts: []string{"*.internal.api.com"}, Cert: "com", Key: "com"}, }, "d", []string{"bar"}) - snapshot := configurator.Generate(ingresses, []*v1.Secret{}) + snapshot, err := configurator.Generate(ingresses, []*v1.Secret{}) + if err != nil { + t.Fatalf("Error generating snapshot %v", err) + } + listener := snapshot.Resources[tcache.Listener].Items["listener_0"].Resource.(*listener.Listener) if len(listener.FilterChains) != 1 { @@ -161,7 +147,11 @@ func TestGenerateIntoTwoCerts(t *testing.T) { {Hosts: []string{"*"}, Cert: "all", Key: "all"}, }, "d", []string{"bar"}) - snapshot := configurator.Generate(ingresses, []*v1.Secret{}) + snapshot, err := configurator.Generate(ingresses, []*v1.Secret{}) + if err != nil { + t.Fatalf("Error generating snapshot %v", err) + } + listener := snapshot.Resources[tcache.Listener].Items["listener_0"].Resource.(*listener.Listener) if len(listener.FilterChains) != 2 { @@ -229,7 +219,10 @@ func TestGenerateListeners(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { configurator := NewKubernetesConfigurator("a", tc.certs, "", nil) - ret := configurator.generateListeners(&envoyConfiguration{VirtualHosts: tc.virtualHost}) + ret, err := configurator.generateListeners(&envoyConfiguration{VirtualHosts: tc.virtualHost}) + if err != nil { + t.Fatalf("Error generating listeners %v", err) + } listener := ret[0].(*listener.Listener) if len(listener.FilterChains) != 1 { t.Fatalf("filterchain number missmatch") diff --git a/pkg/envoy/http_filters.go b/pkg/envoy/http_filters.go index b94c16f..67be464 100644 --- a/pkg/envoy/http_filters.go +++ b/pkg/envoy/http_filters.go @@ -1,7 +1,11 @@ package envoy import ( + "fmt" + + router "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3" hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + "google.golang.org/protobuf/types/known/anypb" ) type httpFilterBuilder struct { @@ -13,7 +17,15 @@ func (b *httpFilterBuilder) Add(filter *hcm.HttpFilter) *httpFilterBuilder { return b } -func (b *httpFilterBuilder) Filters() []*hcm.HttpFilter { - b.Add(&hcm.HttpFilter{Name: "envoy.filters.http.router"}) - return b.filters +func (b *httpFilterBuilder) Filters() ([]*hcm.HttpFilter, error) { + httpFilterConfig, err := anypb.New(&router.Router{}) + if err != nil { + return nil, fmt.Errorf("failed to marshal router config struct to typed struct: %s", err) + } + + b.Add(&hcm.HttpFilter{ + Name: "envoy.filters.http.router", + ConfigType: &hcm.HttpFilter_TypedConfig{TypedConfig: httpFilterConfig}, + }) + return b.filters, nil } diff --git a/pkg/envoy/options.go b/pkg/envoy/options.go index d14b949..4ccef75 100644 --- a/pkg/envoy/options.go +++ b/pkg/envoy/options.go @@ -78,3 +78,10 @@ func WithDefaultRetryOn(defaultRetryOn string) option { c.defaultRetryOn = defaultRetryOn } } + +// WithAccessLog configures the access log formats +func WithAccessLog(accessLogger AccessLogger) option { + return func(c *KubernetesConfigurator) { + c.accessLogger = accessLogger + } +} diff --git a/pkg/envoy/snapshotter.go b/pkg/envoy/snapshotter.go index 6cc138a..ec79843 100644 --- a/pkg/envoy/snapshotter.go +++ b/pkg/envoy/snapshotter.go @@ -1,6 +1,8 @@ package envoy import ( + "context" + cache "github.com/envoyproxy/go-control-plane/pkg/cache/v3" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" @@ -9,21 +11,21 @@ import ( "github.com/uswitch/yggdrasil/pkg/k8s" ) -//Configurator is an interface that implements Generate and NodeID +// Configurator is an interface that implements Generate and NodeID type Configurator interface { - Generate([]*k8s.Ingress, []*v1.Secret) cache.Snapshot + Generate([]*k8s.Ingress, []*v1.Secret) (cache.Snapshot, error) NodeID() string } -//Snapshotter watches for Ingress changes and updates the -//config snapshot +// Snapshotter watches for Ingress changes and updates the +// config snapshot type Snapshotter struct { snapshotCache cache.SnapshotCache configurator Configurator aggregator *k8s.Aggregator } -//NewSnapshotter returns a new Snapshotter +// NewSnapshotter returns a new Snapshotter func NewSnapshotter(snapshotCache cache.SnapshotCache, config Configurator, aggregator *k8s.Aggregator) *Snapshotter { return &Snapshotter{snapshotCache: snapshotCache, configurator: config, aggregator: aggregator} } @@ -38,15 +40,20 @@ func (s *Snapshotter) snapshot() error { return err } - snapshot := s.configurator.Generate(genericIngresses, secrets) + snapshot, err := s.configurator.Generate(genericIngresses, secrets) log.Debugf("took snapshot: %+v", snapshot) - s.snapshotCache.SetSnapshot(s.configurator.NodeID(), snapshot) + s.snapshotCache.SetSnapshot(context.Background(), s.configurator.NodeID(), &snapshot) + return nil } -//Run will periodically refresh the snapshot +func (s *Snapshotter) CurrentSnapshot() (cache.ResourceSnapshot, error) { + return s.snapshotCache.GetSnapshot(s.configurator.NodeID()) +} + +// Run will periodically refresh the snapshot func (s *Snapshotter) Run(a *k8s.Aggregator) { log.Infof("started snapshotter") hadChanges := false