diff --git a/backend/src/common/client/api_server/pipeline_client.go b/backend/src/common/client/api_server/pipeline_client.go index e2d3bd5b4bf6..90d2d4a4d7d7 100644 --- a/backend/src/common/client/api_server/pipeline_client.go +++ b/backend/src/common/client/api_server/pipeline_client.go @@ -202,3 +202,108 @@ func listAllForPipeline(client PipelineInterface, parameters *params.ListPipelin return allResults, nil } + +func (c *PipelineClient) CreatePipelineVersion(parameters *params.CreatePipelineVersionParams) (*model.APIPipelineVersion, + error) { + // Create context with timeout + ctx, cancel := context.WithTimeout(context.Background(), apiServerDefaultTimeout) + defer cancel() + + parameters.Context = ctx + response, err := c.apiClient.PipelineService.CreatePipelineVersion(parameters, PassThroughAuth) + if err != nil { + if defaultError, ok := err.(*params.CreatePipelineVersionDefault); ok { + err = CreateErrorFromAPIStatus(defaultError.Payload.Error, defaultError.Payload.Code) + } else { + err = CreateErrorCouldNotRecoverAPIStatus(err) + } + + return nil, util.NewUserError(err, + fmt.Sprintf("Failed to create pipeline version. Params: '%v'", parameters), + fmt.Sprintf("Failed to create pipeline version from URL '%v'", parameters.Body.PackageURL.PipelineURL)) + } + + return response.Payload, nil +} + +func (c *PipelineClient) ListPipelineVersions(parameters *params.ListPipelineVersionsParams) ( + []*model.APIPipelineVersion, int, string, error) { + // Create context with timeout + ctx, cancel := context.WithTimeout(context.Background(), apiServerDefaultTimeout) + defer cancel() + + // Make service call + parameters.Context = ctx + response, err := c.apiClient.PipelineService.ListPipelineVersions(parameters, PassThroughAuth) + if err != nil { + if defaultError, ok := err.(*params.ListPipelineVersionsDefault); ok { + err = CreateErrorFromAPIStatus(defaultError.Payload.Error, defaultError.Payload.Code) + } else { + err = CreateErrorCouldNotRecoverAPIStatus(err) + } + + return nil, 0, "", util.NewUserError(err, + fmt.Sprintf("Failed to list pipeline versions. Params: '%+v'", parameters), + fmt.Sprintf("Failed to list pipeline versions")) + } + + return response.Payload.Versions, int(response.Payload.TotalSize), response.Payload.NextPageToken, nil +} + +func (c *PipelineClient) GetPipelineVersion(parameters *params.GetPipelineVersionParams) (*model.APIPipelineVersion, + error) { + // Create context with timeout + ctx, cancel := context.WithTimeout(context.Background(), apiServerDefaultTimeout) + defer cancel() + + // Make service call + parameters.Context = ctx + response, err := c.apiClient.PipelineService.GetPipelineVersion(parameters, PassThroughAuth) + if err != nil { + if defaultError, ok := err.(*params.GetPipelineVersionDefault); ok { + err = CreateErrorFromAPIStatus(defaultError.Payload.Error, defaultError.Payload.Code) + } else { + err = CreateErrorCouldNotRecoverAPIStatus(err) + } + + return nil, util.NewUserError(err, + fmt.Sprintf("Failed to get pipeline version. Params: '%v'", parameters), + fmt.Sprintf("Failed to get pipeline version '%v'", parameters.VersionID)) + } + + return response.Payload, nil +} + +func (c *PipelineClient) GetPipelineVersionTemplate(parameters *params.GetPipelineVersionTemplateParams) ( + *workflowapi.Workflow, error) { + // Create context with timeout + ctx, cancel := context.WithTimeout(context.Background(), apiServerDefaultTimeout) + defer cancel() + + // Make service call + parameters.Context = ctx + response, err := c.apiClient.PipelineService.GetPipelineVersionTemplate(parameters, PassThroughAuth) + if err != nil { + if defaultError, ok := err.(*params.GetPipelineVersionTemplateDefault); ok { + err = CreateErrorFromAPIStatus(defaultError.Payload.Error, defaultError.Payload.Code) + } else { + err = CreateErrorCouldNotRecoverAPIStatus(err) + } + + return nil, util.NewUserError(err, + fmt.Sprintf("Failed to get template. Params: '%+v'", parameters), + fmt.Sprintf("Failed to get template for pipeline version '%v'", parameters.VersionID)) + } + + // Unmarshal response + var workflow workflowapi.Workflow + err = yaml.Unmarshal([]byte(response.Payload.Template), &workflow) + if err != nil { + return nil, util.NewUserError(err, + fmt.Sprintf("Failed to unmarshal reponse. Params: '%+v'. Response: '%s'", parameters, + response.Payload.Template), + fmt.Sprintf("Failed to unmarshal reponse")) + } + + return &workflow, nil +} diff --git a/backend/src/common/client/api_server/pipeline_upload_client.go b/backend/src/common/client/api_server/pipeline_upload_client.go index 0d8d7cb14de2..476745b85776 100644 --- a/backend/src/common/client/api_server/pipeline_upload_client.go +++ b/backend/src/common/client/api_server/pipeline_upload_client.go @@ -85,5 +85,37 @@ func (c *PipelineUploadClient) Upload(parameters *params.UploadPipelineParams) ( return response.Payload, nil } -// TODO(jingzhang36): add UploadPipelineVersion after go_http_client and go_client are -// auto-generated from UploadPipelineVersion in PipelineUploadServer +// UploadPipelineVersion uploads pipeline version from local file. +func (c *PipelineUploadClient) UploadPipelineVersion(filePath string, parameters *params.UploadPipelineVersionParams) (*model.APIPipelineVersion, + error) { + // Get file + file, err := os.Open(filePath) + if err != nil { + return nil, util.NewUserErrorWithSingleMessage(err, + fmt.Sprintf("Failed to open file '%s'", filePath)) + } + defer file.Close() + parameters.Uploadfile = runtime.NamedReader(filePath, file) + + // Create context with timeout + ctx, cancel := context.WithTimeout(context.Background(), apiServerDefaultTimeout) + defer cancel() + + // Make service call + parameters.Context = ctx + response, err := c.apiClient.PipelineUploadService.UploadPipelineVersion(parameters, PassThroughAuth) + + if err != nil { + if defaultError, ok := err.(*params.UploadPipelineVersionDefault); ok { + err = CreateErrorFromAPIStatus(defaultError.Payload.Error, defaultError.Payload.Code) + } else { + err = CreateErrorCouldNotRecoverAPIStatus(err) + } + + return nil, util.NewUserError(err, + fmt.Sprintf("Failed to upload pipeline version. Params: '%v'", parameters), + fmt.Sprintf("Failed to upload pipeline version")) + } + + return response.Payload, nil +} diff --git a/backend/test/integration/BUILD.bazel b/backend/test/integration/BUILD.bazel index e331cb08d5f5..30f148d529ce 100644 --- a/backend/test/integration/BUILD.bazel +++ b/backend/test/integration/BUILD.bazel @@ -6,6 +6,7 @@ go_test( "experiment_api_test.go", "job_api_test.go", "pipeline_api_test.go", + "pipeline_version_api_test.go", "run_api_test.go", "visualization_api_test.go", ], diff --git a/backend/test/integration/pipeline_api_test.go b/backend/test/integration/pipeline_api_test.go index a2049593d96d..8e4e2a9d1d1b 100644 --- a/backend/test/integration/pipeline_api_test.go +++ b/backend/test/integration/pipeline_api_test.go @@ -197,9 +197,6 @@ func verifyPipeline(t *testing.T, pipeline *model.APIPipeline) { {Name: "param1", Value: "hello"}, // Default value in the pipeline template {Name: "param2"}, // No default value in the pipeline }, - // TODO(jingzhang36): after version API launch, remove the following field. - // This is because after the version API launch, we won't have defautl - // version produced automatically when creating pipeline. DefaultVersion: &model.APIPipelineVersion{ CreatedAt: pipeline.CreatedAt, ID: pipeline.ID, @@ -218,8 +215,6 @@ func TestPipelineAPI(t *testing.T) { suite.Run(t, new(PipelineApiTest)) } -// TODO(jingzhang36): include UploadPipelineVersion in integration test - func (s *PipelineApiTest) TearDownSuite() { if *runIntegrationTests { if !*isDevMode { diff --git a/backend/test/integration/pipeline_version_api_test.go b/backend/test/integration/pipeline_version_api_test.go new file mode 100644 index 000000000000..c5eccef05365 --- /dev/null +++ b/backend/test/integration/pipeline_version_api_test.go @@ -0,0 +1,298 @@ +package integration + +import ( + "io/ioutil" + "testing" + "time" + + "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" + "github.com/ghodss/yaml" + "github.com/golang/glog" + params "github.com/kubeflow/pipelines/backend/api/go_http_client/pipeline_client/pipeline_service" + "github.com/kubeflow/pipelines/backend/api/go_http_client/pipeline_model" + uploadParams "github.com/kubeflow/pipelines/backend/api/go_http_client/pipeline_upload_client/pipeline_upload_service" + "github.com/kubeflow/pipelines/backend/src/common/client/api_server" + "github.com/kubeflow/pipelines/backend/src/common/util" + "github.com/kubeflow/pipelines/backend/test" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +// This test suit tests various methods to import pipeline to pipeline system, including +// - upload yaml file +// - upload tarball file +// - providing YAML file url +// - Providing tarball file url +type PipelineVersionApiTest struct { + suite.Suite + pipelineClient *api_server.PipelineClient + pipelineUploadClient *api_server.PipelineUploadClient +} + +// Check the namespace have ML job installed and ready +func (s *PipelineVersionApiTest) SetupTest() { + if !*runIntegrationTests { + s.T().SkipNow() + return + } + + if !*isDevMode { + err := test.WaitForReady(*namespace, *initializeTimeout) + if err != nil { + glog.Exitf("Failed to initialize test. Error: %s", err.Error()) + } + } + clientConfig := test.GetClientConfig(*namespace) + var err error + s.pipelineUploadClient, err = api_server.NewPipelineUploadClient(clientConfig, false) + if err != nil { + glog.Exitf("Failed to get pipeline upload client. Error: %s", err.Error()) + } + s.pipelineClient, err = api_server.NewPipelineClient(clientConfig, false) + if err != nil { + glog.Exitf("Failed to get pipeline client. Error: %s", err.Error()) + } + + s.cleanUp() +} + +func (s *PipelineVersionApiTest) TestPipelineVersionAPI() { + t := s.T() + + test.DeleteAllPipelines(s.pipelineClient, t) + + /* ---------- Upload a pipeline YAML ---------- */ + pipelineParams := uploadParams.NewUploadPipelineParams() + pipelineName := "test_pipeline" + pipelineParams.SetName(&pipelineName) + pipeline, err := s.pipelineUploadClient.UploadFile("../resources/arguments-parameters.yaml", pipelineParams) + assert.Nil(t, err) + assert.Equal(t, "test_pipeline", pipeline.Name) + + /* ---------- Get pipeline id ---------- */ + pipelines, totalSize, _, err := s.pipelineClient.List(params.NewListPipelinesParams()) + assert.Nil(t, err) + assert.Equal(t, 1, len(pipelines)) + assert.Equal(t, 1, totalSize) + pipelineId := pipelines[0].ID + + /* ---------- Upload a pipeline version YAML under test_pipeline ---------- */ + time.Sleep(1 * time.Second) + pipelineVersionParams := uploadParams.NewUploadPipelineVersionParams() + pipelineVersionParams.SetPipelineid(&pipelineId) + argumentYAMLPipelineVersion, err := s.pipelineUploadClient.UploadPipelineVersion("../resources/arguments-parameters.yaml", pipelineVersionParams) + assert.Nil(t, err) + assert.Equal(t, "arguments-parameters.yaml", argumentYAMLPipelineVersion.Name) + + /* ---------- Upload the same pipeline version again. Should fail due to name uniqueness ---------- */ + _, err = s.pipelineUploadClient.UploadPipelineVersion("../resources/arguments-parameters.yaml", uploadParams.NewUploadPipelineVersionParams()) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "Failed to upload pipeline version.") + + /* ---------- Import pipeline version YAML by URL ---------- */ + time.Sleep(1 * time.Second) + sequentialPipelineVersion, err := s.pipelineClient.CreatePipelineVersion(¶ms.CreatePipelineVersionParams{ + Body: &pipeline_model.APIPipelineVersion{ + Name: "sequential", + PackageURL: &pipeline_model.APIURL{ + PipelineURL: "https://storage.googleapis.com/ml-pipeline-dataset/sequential.yaml", + }, + ResourceReferences: []*pipeline_model.APIResourceReference{ + { + Key: &pipeline_model.APIResourceKey{Type: pipeline_model.APIResourceTypePIPELINE, ID: pipelineId}, + Relationship: pipeline_model.APIRelationshipOWNER, + }, + }, + }}) + assert.Nil(t, err) + assert.Equal(t, "sequential", sequentialPipelineVersion.Name) + + /* ---------- Upload pipeline version zip ---------- */ + time.Sleep(1 * time.Second) + argumentUploadPipelineVersion, err := s.pipelineUploadClient.UploadPipelineVersion( + "../resources/arguments.pipeline.zip", &uploadParams.UploadPipelineVersionParams{ + Name: util.StringPointer("zip-arguments-parameters"), + Pipelineid: util.StringPointer(pipelineId), + }) + assert.Nil(t, err) + assert.Equal(t, "zip-arguments-parameters", argumentUploadPipelineVersion.Name) + + /* ---------- Import pipeline tarball by URL ---------- */ + time.Sleep(1 * time.Second) + argumentUrlPipelineVersion, err := s.pipelineClient.CreatePipelineVersion(¶ms.CreatePipelineVersionParams{ + Body: &pipeline_model.APIPipelineVersion{ + Name: "arguments", + PackageURL: &pipeline_model.APIURL{ + PipelineURL: "https://storage.googleapis.com/ml-pipeline-dataset/arguments.pipeline.zip", + }, + ResourceReferences: []*pipeline_model.APIResourceReference{ + { + Key: &pipeline_model.APIResourceKey{Type: pipeline_model.APIResourceTypePIPELINE, ID: pipelineId}, + Relationship: pipeline_model.APIRelationshipOWNER, + }, + }, + }}) + assert.Nil(t, err) + assert.Equal(t, "arguments", argumentUrlPipelineVersion.Name) + + /* ---------- Verify list pipeline version works ---------- */ + pipelineVersions, totalSize, _, err := s.pipelineClient.ListPipelineVersions(¶ms.ListPipelineVersionsParams{ + ResourceKeyID: util.StringPointer(pipelineId), + ResourceKeyType: util.StringPointer("PIPELINE"), + }) + assert.Nil(t, err) + assert.Equal(t, 5, len(pipelineVersions)) + assert.Equal(t, 5, totalSize) + for _, p := range pipelineVersions { + assert.NotNil(t, *p) + assert.NotNil(t, p.CreatedAt) + assert.Contains(t, []string{"test_pipeline" /*default version created with pipeline*/, "sequential", "arguments", "arguments-parameters.yaml", "zip-arguments-parameters"}, p.Name) + + if p.Name == "arguments" { + assert.Equal(t, p.Parameters, + []*pipeline_model.APIParameter{ + {Name: "param1", Value: "hello"}, // Default value in the pipeline template + {Name: "param2"}, // No default value in the pipeline + }) + } + } + + /* ---------- Verify list pipeline sorted by names ---------- */ + listFirstPagePipelineVersions, totalSize, nextPageToken, err := s.pipelineClient.ListPipelineVersions( + ¶ms.ListPipelineVersionsParams{ + PageSize: util.Int32Pointer(3), + SortBy: util.StringPointer("name"), + ResourceKeyID: util.StringPointer(pipelineId), + ResourceKeyType: util.StringPointer("PIPELINE"), + }) + assert.Nil(t, err) + assert.Equal(t, 3, len(listFirstPagePipelineVersions)) + assert.Equal(t, 5, totalSize) + assert.Equal(t, "arguments", listFirstPagePipelineVersions[0].Name) + assert.Equal(t, "arguments-parameters.yaml", listFirstPagePipelineVersions[1].Name) + assert.Equal(t, "sequential", listFirstPagePipelineVersions[2].Name) + assert.NotEmpty(t, nextPageToken) + + listSecondPagePipelineVersions, totalSize, nextPageToken, err := s.pipelineClient.ListPipelineVersions( + ¶ms.ListPipelineVersionsParams{ + PageToken: util.StringPointer(nextPageToken), + PageSize: util.Int32Pointer(3), + SortBy: util.StringPointer("name"), + ResourceKeyID: util.StringPointer(pipelineId), + ResourceKeyType: util.StringPointer("PIPELINE"), + }) + assert.Nil(t, err) + assert.Equal(t, 2, len(listSecondPagePipelineVersions)) + assert.Equal(t, 5, totalSize) + assert.Equal(t, "test_pipeline", listSecondPagePipelineVersions[0].Name) + assert.Equal(t, "zip-arguments-parameters", listSecondPagePipelineVersions[1].Name) + assert.Empty(t, nextPageToken) + + /* ---------- Verify list pipeline version sorted by creation time ---------- */ + listFirstPagePipelineVersions, totalSize, nextPageToken, err = s.pipelineClient.ListPipelineVersions( + ¶ms.ListPipelineVersionsParams{ + PageSize: util.Int32Pointer(3), + SortBy: util.StringPointer("created_at"), + ResourceKeyID: util.StringPointer(pipelineId), + ResourceKeyType: util.StringPointer("PIPELINE"), + }) + assert.Nil(t, err) + assert.Equal(t, 3, len(listFirstPagePipelineVersions)) + assert.Equal(t, 5, totalSize) + assert.Equal(t, "test_pipeline", listFirstPagePipelineVersions[0].Name) + assert.Equal(t, "arguments-parameters.yaml", listFirstPagePipelineVersions[1].Name) + assert.Equal(t, "sequential", listFirstPagePipelineVersions[2].Name) + assert.NotEmpty(t, nextPageToken) + + listSecondPagePipelineVersions, totalSize, nextPageToken, err = s.pipelineClient.ListPipelineVersions( + ¶ms.ListPipelineVersionsParams{ + PageToken: util.StringPointer(nextPageToken), + PageSize: util.Int32Pointer(3), + SortBy: util.StringPointer("created_at"), + ResourceKeyID: util.StringPointer(pipelineId), + ResourceKeyType: util.StringPointer("PIPELINE"), + }) + assert.Nil(t, err) + assert.Equal(t, 2, len(listSecondPagePipelineVersions)) + assert.Equal(t, 5, totalSize) + assert.Equal(t, "zip-arguments-parameters", listSecondPagePipelineVersions[0].Name) + assert.Equal(t, "arguments", listSecondPagePipelineVersions[1].Name) + assert.Empty(t, nextPageToken) + + /* ---------- List pipeline versions sort by unsupported description field. Should fail. ---------- */ + _, _, _, err = s.pipelineClient.ListPipelineVersions(¶ms.ListPipelineVersionsParams{ + PageSize: util.Int32Pointer(2), + SortBy: util.StringPointer("unknownfield"), + ResourceKeyID: util.StringPointer(pipelineId), + ResourceKeyType: util.StringPointer("PIPELINE"), + }) + assert.NotNil(t, err) + + /* ---------- List pipeline versions sorted by names descend order ---------- */ + listFirstPagePipelineVersions, totalSize, nextPageToken, err = s.pipelineClient.ListPipelineVersions( + ¶ms.ListPipelineVersionsParams{ + PageSize: util.Int32Pointer(3), + SortBy: util.StringPointer("name desc"), + ResourceKeyID: util.StringPointer(pipelineId), + ResourceKeyType: util.StringPointer("PIPELINE"), + }) + assert.Nil(t, err) + assert.Equal(t, 3, len(listFirstPagePipelineVersions)) + assert.Equal(t, 5, totalSize) + assert.Equal(t, "zip-arguments-parameters", listFirstPagePipelineVersions[0].Name) + assert.Equal(t, "test_pipeline", listFirstPagePipelineVersions[1].Name) + assert.Equal(t, "sequential", listFirstPagePipelineVersions[2].Name) + assert.NotEmpty(t, nextPageToken) + + listSecondPagePipelineVersions, totalSize, nextPageToken, err = s.pipelineClient.ListPipelineVersions( + ¶ms.ListPipelineVersionsParams{ + PageToken: util.StringPointer(nextPageToken), + PageSize: util.Int32Pointer(3), + SortBy: util.StringPointer("name desc"), + ResourceKeyID: util.StringPointer(pipelineId), + ResourceKeyType: util.StringPointer("PIPELINE"), + }) + assert.Nil(t, err) + assert.Equal(t, 2, len(listSecondPagePipelineVersions)) + assert.Equal(t, 5, totalSize) + assert.Equal(t, "arguments-parameters.yaml", listSecondPagePipelineVersions[0].Name) + assert.Equal(t, "arguments", listSecondPagePipelineVersions[1].Name) + assert.Empty(t, nextPageToken) + + /* ---------- Verify get pipeline version works ---------- */ + pipelineVersion, err := s.pipelineClient.GetPipelineVersion(¶ms.GetPipelineVersionParams{VersionID: argumentUrlPipelineVersion.ID}) + assert.Nil(t, err) + assert.Equal(t, pipelineVersion.Name, "arguments") + assert.NotNil(t, pipelineVersion.CreatedAt) + assert.Equal(t, pipelineVersion.Parameters, + []*pipeline_model.APIParameter{ + {Name: "param1", Value: "hello"}, + {Name: "param2"}, + }) + + /* ---------- Verify get template works ---------- */ + template, err := s.pipelineClient.GetPipelineVersionTemplate(¶ms.GetPipelineVersionTemplateParams{VersionID: argumentYAMLPipelineVersion.ID}) + assert.Nil(t, err) + expected, err := ioutil.ReadFile("../resources/arguments-parameters.yaml") + assert.Nil(t, err) + var expectedWorkflow v1alpha1.Workflow + err = yaml.Unmarshal(expected, &expectedWorkflow) + assert.Equal(t, expectedWorkflow, *template) +} + +func TestPipelineVersionAPI(t *testing.T) { + suite.Run(t, new(PipelineVersionApiTest)) +} + +func (s *PipelineVersionApiTest) TearDownSuite() { + if *runIntegrationTests { + if !*isDevMode { + s.cleanUp() + } + } +} + +func (s *PipelineVersionApiTest) cleanUp() { + // Delete pipelines will delete pipelines and their versions. + test.DeleteAllPipelines(s.pipelineClient, s.T()) +} diff --git a/go.mod b/go.mod index 4df30170f932..5db7ad3b6f75 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,8 @@ require ( github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c // indirect github.com/spf13/viper v1.3.0 - github.com/stretchr/testify v1.2.2 + github.com/stretchr/objx v0.2.0 // indirect + github.com/stretchr/testify v1.3.0 github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 // indirect go.uber.org/atomic v1.3.2 // indirect diff --git a/go.sum b/go.sum index f55c8d15090b..e5c628805abe 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f h1:WH0w/R4Yoey+04HhFxqZ6VX6I0d7RMyw5aXQ9UTvQPs= @@ -96,6 +97,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -221,8 +223,13 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.0 h1:cO6QlTTeK9RQDhFAbGLV5e3fHXbRpin/Gi8qfL4rdLk= github.com/spf13/viper v1.3.0/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=