Skip to content

Commit

Permalink
Cortex Exporter Send Pipeline (#210)
Browse files Browse the repository at this point in the history
* Add addHeaders for adding headers to a HTTP request and TestAddHeaders

* Add buildMessage for creating a compressed protobuf message and tests

* Add buildRequest for creating the HTTP request and TestBuildRequest

* Add sendRequest, TestSendRequest, and test helper function

* Run make precommit

* Change test helper function name, adjust comments, run make precommit
  • Loading branch information
Eric Lee committed Aug 12, 2020
1 parent 020b7b5 commit 6fd38b9
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 1 deletion.
79 changes: 79 additions & 0 deletions exporters/metric/cortex/cortex.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@
package cortex

import (
"bytes"
"context"
"fmt"
"net/http"

"github.com/gogo/protobuf/proto"
"github.com/golang/snappy"
"github.com/prometheus/prometheus/prompb"

"go.opentelemetry.io/otel/api/global"
apimetric "go.opentelemetry.io/otel/api/metric"
Expand Down Expand Up @@ -78,3 +85,75 @@ func InstallNewPipeline(config Config, options ...push.Option) (*push.Controller
global.SetMeterProvider(pusher.Provider())
return pusher, nil
}

// addHeaders adds required headers as well as all headers in Header map to a http
// request.
func (e *Exporter) addHeaders(req *http.Request) {
// Cortex expects Snappy-compressed protobuf messages. These three headers are
// hard-coded as they should be on every request.
req.Header.Add("X-Prometheus-Remote-Write-Version", "0.1.0")
req.Header.Add("Content-Encoding", "snappy")
req.Header.Set("Content-Type", "application/x-protobuf")

// Add all user-supplied headers to the request.
for name, field := range e.config.Headers {
req.Header.Add(name, field)
}
}

// buildMessage creates a Snappy-compressed protobuf message from a slice of TimeSeries.
func (e *Exporter) buildMessage(timeseries []*prompb.TimeSeries) ([]byte, error) {
// Wrap the TimeSeries as a WriteRequest since Cortex requires it.
writeRequest := &prompb.WriteRequest{
Timeseries: timeseries,
}

// Convert the struct to a slice of bytes and then compress it.
message, err := proto.Marshal(writeRequest)
if err != nil {
return nil, err
}
compressed := snappy.Encode(nil, message)

return compressed, nil
}

// buildRequest creates an http POST request with a Snappy-compressed protocol buffer
// message as the body and with all the headers attached.
func (e *Exporter) buildRequest(message []byte) (*http.Request, error) {
req, err := http.NewRequest(
http.MethodPost,
e.config.Endpoint,
bytes.NewBuffer(message),
)
if err != nil {
return nil, err
}

// Add the required headers and the headers from Config.Headers.
e.addHeaders(req)

return req, nil
}

// sendRequest sends an http request using the Exporter's http Client.
func (e *Exporter) sendRequest(req *http.Request) error {
// Set a client if the user didn't provide one.
if e.config.Client == nil {
e.config.Client = http.DefaultClient
e.config.Client.Timeout = e.config.RemoteTimeout
}

// Attempt to send request.
res, err := e.config.Client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()

// The response should have a status code of 200.
if res.StatusCode != http.StatusOK {
return fmt.Errorf("%v", res.Status)
}
return nil
}
176 changes: 176 additions & 0 deletions exporters/metric/cortex/cortex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,19 @@
package cortex

import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"strconv"
"testing"
"time"

"github.com/gogo/protobuf/proto"
"github.com/golang/snappy"
"github.com/google/go-cmp/cmp"
"github.com/prometheus/prometheus/prompb"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/sdk/export/metric"
Expand Down Expand Up @@ -97,3 +105,171 @@ func TestInstallNewPipeline(t *testing.T) {
t.Fatalf("Failed to register push Controller provider globally")
}
}

// TestAddHeaders tests whether the correct headers are correctly added to a http request.
func TestAddHeaders(t *testing.T) {
testConfig := Config{
Headers: map[string]string{
"TestHeaderOne": "TestFieldTwo",
"TestHeaderTwo": "TestFieldTwo",
},
}
exporter := Exporter{testConfig}

// Create http request to add headers to.
req, err := http.NewRequest("POST", "test.com", nil)
require.Nil(t, err)
exporter.addHeaders(req)

// Check that all the headers are there.
for name, field := range testConfig.Headers {
require.Equal(t, req.Header.Get(name), field)
}
require.Equal(t, req.Header.Get("Content-Encoding"), "snappy")
require.Equal(t, req.Header.Get("Content-Type"), "application/x-protobuf")
require.Equal(t, req.Header.Get("X-Prometheus-Remote-Write-Version"), "0.1.0")
}

// TestBuildMessage tests whether BuildMessage successfully returns a Snappy-compressed
// protobuf message.
func TestBuildMessage(t *testing.T) {
exporter := Exporter{validConfig}
timeseries := []*prompb.TimeSeries{}

// buildMessage returns the error that proto.Marshal() returns. Since the proto
// package has its own tests, buildMessage should work as expected as long as there
// are no errors.
_, err := exporter.buildMessage(timeseries)
require.Nil(t, err)
}

// TestBuildRequest tests whether a http request is a POST request, has the correct body,
// and has the correct headers.
func TestBuildRequest(t *testing.T) {
// Make fake exporter and message for testing.
var testMessage = []byte(`Test Message`)
exporter := Exporter{validConfig}

// Create the http request.
req, err := exporter.buildRequest(testMessage)
require.Nil(t, err)

// Verify the http method, url, and body.
require.Equal(t, req.Method, http.MethodPost)
require.Equal(t, req.URL.String(), validConfig.Endpoint)

reqMessage, err := ioutil.ReadAll(req.Body)
require.Nil(t, err)
require.Equal(t, reqMessage, testMessage)

// Verify headers.
for name, field := range exporter.config.Headers {
require.Equal(t, req.Header.Get(name), field)
}
require.Equal(t, req.Header.Get("Content-Encoding"), "snappy")
require.Equal(t, req.Header.Get("Content-Type"), "application/x-protobuf")
require.Equal(t, req.Header.Get("X-Prometheus-Remote-Write-Version"), "0.1.0")
}

// verifyExporterRequest checks a HTTP request from the export pipeline. It checks whether
// the request contains a correctly formatted remote_write body and the required headers.
func verifyExporterRequest(req *http.Request) error {
// Check for required headers.
if req.Header.Get("X-Prometheus-Remote-Write-Version") != "0.1.0" ||
req.Header.Get("Content-Encoding") != "snappy" ||
req.Header.Get("Content-Type") != "application/x-protobuf" {
return fmt.Errorf("Request does not contain the three required headers")
}

// Check body format and headers.
compressed, err := ioutil.ReadAll(req.Body)
if err != nil {
return fmt.Errorf("Failed to read request body")
}
uncompressed, err := snappy.Decode(nil, compressed)
if err != nil {
return fmt.Errorf("Failed to uncompress request body")
}
wr := &prompb.WriteRequest{}
err = proto.Unmarshal(uncompressed, wr)
if err != nil {
return fmt.Errorf("Failed to unmarshal message into WriteRequest struct")
}

return nil
}

// TestSendRequest checks if the Exporter can successfully send a http request with a
// correctly formatted body and the correct headers. A test server returns different
// status codes to test if the Exporter responds to a send failure correctly.
func TestSendRequest(t *testing.T) {
tests := []struct {
testName string
config *Config
expectedError error
isStatusNotFound bool
}{
{
testName: "Successful Export",
config: &validConfig,
expectedError: nil,
isStatusNotFound: false,
},
{
testName: "Export Failure",
config: &Config{},
expectedError: fmt.Errorf("%v", "404 Not Found"),
isStatusNotFound: true,
},
}

// Set up a test server to receive the request. The server responds with a 400 Bad
// Request status code if any headers are missing or if the body is not of the correct
// format. Additionally, the server can respond with status code 404 Not Found to
// simulate send failures.
handler := func(rw http.ResponseWriter, req *http.Request) {
err := verifyExporterRequest(req)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
return
}

// Return a status code 400 if header isStatusNotFound is "true", 200 otherwise.
if req.Header.Get("isStatusNotFound") == "true" {
rw.WriteHeader(http.StatusNotFound)
} else {
rw.WriteHeader(http.StatusOK)
}
}
server := httptest.NewServer(http.HandlerFunc(handler))
defer server.Close()

for _, test := range tests {
t.Run(test.testName, func(t *testing.T) {
// Set up an Exporter that uses the test server's endpoint and attaches the
// test's isStatusNotFound header.
test.config.Endpoint = server.URL
test.config.Headers = map[string]string{
"isStatusNotFound": strconv.FormatBool(test.isStatusNotFound),
}
exporter := Exporter{*test.config}

// Create an empty Snappy-compressed message.
msg, err := exporter.buildMessage([]*prompb.TimeSeries{})
require.Nil(t, err)

// Create a http POST request with the compressed message.
req, err := exporter.buildRequest(msg)
require.Nil(t, err)

// Send the request to the test server and verify the error.
err = exporter.sendRequest(req)
if err != nil {
errorString := err.Error()
require.Equal(t, errorString, test.expectedError.Error())
} else {
require.Nil(t, test.expectedError)
}
})
}
}
4 changes: 4 additions & 0 deletions exporters/metric/cortex/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ module go.opentelemetry.io/contrib/exporters/metric/cortex
go 1.14

require (
github.com/gogo/protobuf v1.3.1
github.com/golang/snappy v0.0.1
github.com/google/go-cmp v0.5.1
github.com/grpc-ecosystem/grpc-gateway v1.14.6 // indirect
github.com/prometheus/prometheus v2.5.0+incompatible
github.com/stretchr/testify v1.6.1
go.opentelemetry.io/otel v0.10.0
go.opentelemetry.io/otel/sdk v0.10.0
Expand Down
30 changes: 29 additions & 1 deletion exporters/metric/cortex/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DataDog/sketches-go v0.0.1 h1:RtG+76WKgZuz6FIaGsjoPePmadDBkuD/KC6+ZWu78b8=
github.com/DataDog/sketches-go v0.0.1/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/benbjohnson/clock v1.0.3 h1:vkLuvpK4fmtSCuo60+yC63p7y0BmQ8gm5ZXGuBCJyXg=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand All @@ -11,8 +13,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand All @@ -25,6 +31,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
Expand All @@ -33,6 +41,10 @@ github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o=
github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand All @@ -42,6 +54,10 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/prometheus v2.5.0+incompatible h1:7QPitgO2kOFG8ecuRn9O/4L9+10He72rVRJvMXrE9Hg=
github.com/prometheus/prometheus v2.5.0+incompatible/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
Expand All @@ -57,17 +73,25 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
Expand All @@ -78,11 +102,14 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 h1:4HYDjxeNXAOTv3o1N2tjo8UUSlhQgAD52FVkwxnWgM8=
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 h1:fiNLklpBwWK1mth30Hlwk+fcdBmIALlgF5iy77O37Ig=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
Expand All @@ -95,6 +122,7 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
Loading

0 comments on commit 6fd38b9

Please sign in to comment.