diff --git a/backend/repository/endpoint_update.go b/backend/repository/endpoint_update.go index af5eec655..69c46d85a 100644 --- a/backend/repository/endpoint_update.go +++ b/backend/repository/endpoint_update.go @@ -25,7 +25,6 @@ import ( "path/filepath" "strings" - "encoding/json" "github.com/pkg/errors" "github.com/uber/zanzibar/codegen" ) @@ -87,17 +86,9 @@ func (r *Repository) validateEndpointCfg(req *EndpointConfig) error { for _, mid := range req.Middlewares { for _, midCfg := range r.gatewayConfig.Middlewares { if mid.Name == midCfg.Name { - result, err := r.validator.ValidateGo(midCfg.SchemaFile, mid.Options) - if err != nil && result != nil { - resultErrors, _ := json.Marshal(result.Errors()) - return errors.Wrap(err, "schema validation error\nErrors:\n"+string(resultErrors)) - } - if err != nil { - return errors.Wrap(err, "schema validation error unknown") - } - if !result.Valid() { - resultErrors, _ := json.Marshal(result.Errors()) - return errors.New("schema validation error :\n" + string(resultErrors)) + err := codegen.SchemaValidateGo(midCfg.SchemaFile, mid.Options) + if err != nil { + return err } } } diff --git a/backend/repository/repository.go b/backend/repository/repository.go index f3e765788..4affe88d8 100644 --- a/backend/repository/repository.go +++ b/backend/repository/repository.go @@ -25,7 +25,6 @@ import ( "time" "github.com/pkg/errors" - "github.com/uber/zanzibar/codegen" ) // Repository operates one local repository: @@ -45,7 +44,6 @@ type Repository struct { // Cached error when getting gateway config. gatewayConfigError error sync.RWMutex - validator *codegen.SchemaValidator } // Fetcher fetches remote repository to local repository. @@ -80,7 +78,6 @@ func NewRepository(localRoot, remote string, fetcher Fetcher, fetcher: fetcher, lastUpdateTime: time.Now(), refreshInterval: refreshInterval, - validator: &codegen.SchemaValidator{}, }, nil } diff --git a/codegen/schema_validator.go b/codegen/schema_validator.go index e7ec9993a..fe21dec34 100644 --- a/codegen/schema_validator.go +++ b/codegen/schema_validator.go @@ -20,59 +20,40 @@ package codegen -import "github.com/xeipuuv/gojsonschema" - -// ResultError abstracts a subset of interface in gojsonschema -type ResultError interface { - Field() string - Type() string - Description() string - Value() interface{} - String() string -} - -// Result interface type subset of gojsonschema -type Result interface { - Valid() bool - Errors() []ResultError -} - -type resultStruct struct { - valid bool - errors []ResultError -} - -func (r *resultStruct) Valid() bool { - return r.valid -} - -func (r *resultStruct) Errors() []ResultError { - return r.errors -} - -// SchemaValidator abstracts undlerlying schema validation library -type SchemaValidator struct{} - -// ValidateGo performs JSON schema validation from schema file on to arbitrary Go object -func (s *SchemaValidator) ValidateGo(schemaFile string, arbitraryObj map[string]interface{}) (Result, error) { +import ( + "encoding/json" + "fmt" + "github.com/pkg/errors" + "github.com/xeipuuv/gojsonschema" +) + +// SchemaValidateGo performs JSON schema validation from schema file on to arbitrary Go object +func SchemaValidateGo(schemaFile string, arbitraryObj map[string]interface{}) error { // gojsonschmea caches schema validators schemaLoader := gojsonschema.NewReferenceLoader(schemaFile) jsonLoader := gojsonschema.NewGoLoader(arbitraryObj) - res, err := gojsonschema.Validate(schemaLoader, jsonLoader) + result, err := gojsonschema.Validate(schemaLoader, jsonLoader) - if res == nil { - return nil, err + if err != nil && result != nil { + resultErrors, _ := json.Marshal(result.Errors()) + return errors.Wrap(err, "schema validation error\nErrors:\n"+string(resultErrors)) } - - // convert gojsonschema to our result type - resultErrors := res.Errors() - myResult := &resultStruct{ - res.Valid(), - make([]ResultError, len(res.Errors())), + if err != nil { + return errors.Wrap(err, "schema validation error unknown") } - for i, resultError := range resultErrors { - myResult.errors[i] = resultError.(ResultError) + if !result.Valid() { + msg := "schema validation error :" + for _, resErr := range result.Errors() { + + details, _ := json.Marshal(resErr.Details()) + msg += fmt.Sprintf("\nType: %s\nField: %s\nDescription: %s\nDetails: %s\n", + resErr.Type(), + resErr.Field(), + resErr.Description(), + string(details), + ) + } + return errors.New(msg) } - - return myResult, err + return nil } diff --git a/codegen/schema_validator_test.go b/codegen/schema_validator_test.go index cf06bb3d5..f502edd14 100644 --- a/codegen/schema_validator_test.go +++ b/codegen/schema_validator_test.go @@ -28,9 +28,6 @@ import ( ) func TestSchemaValidatorSuccess(t *testing.T) { - - validator := &codegen.SchemaValidator{} - var obj map[string]interface{} obj = make(map[string]interface{}) obj["foo"] = true @@ -39,18 +36,11 @@ func TestSchemaValidatorSuccess(t *testing.T) { assert.NoError(t, err) canonFileRef := "file://" + absPath - res, err := validator.ValidateGo(canonFileRef, obj) - assert.NoError(t, err) - if res != nil { - assert.True(t, res.Valid()) - } else { - assert.Fail(t, "res was nil") - } - + vErr := codegen.SchemaValidateGo(canonFileRef, obj) + assert.NoError(t, vErr) } func TestSchemaValidatorFail(t *testing.T) { - validator := &codegen.SchemaValidator{} var obj map[string]interface{} obj = make(map[string]interface{}) @@ -60,13 +50,6 @@ func TestSchemaValidatorFail(t *testing.T) { assert.NoError(t, err) canonFileRef := "file://" + absPath - res, err := validator.ValidateGo(canonFileRef, obj) - assert.NoError(t, err) - if res != nil { - assert.False(t, res.Valid()) - assert.Equal(t, res.Errors()[0].Description(), "Invalid type. Expected: boolean, given: integer") - } else { - assert.Fail(t, "res was nil") - } - + vErr := codegen.SchemaValidateGo(canonFileRef, obj) + assert.Error(t, vErr) } diff --git a/glide.lock b/glide.lock index 98079f3fc..983cc5c36 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: e366f9396641da4ac4004240705229287a40b9aca78aa08800e53ea847d1a8ee -updated: 2017-09-28T14:20:09.140905199-07:00 +hash: fbdcb4f002ab8988bc67d7cb4c23e229105dedd734612f2194117543ac170827 +updated: 2017-10-02T15:39:18.990686513-07:00 imports: - name: github.com/anmitsu/go-shlex version: 648efa622239a2f6ff949fed78ee37b48d499ba4 @@ -61,7 +61,7 @@ imports: - name: github.com/uber-go/atomic version: e682c1008ac17bf26d2e4b5ad6cdd08520ed0b22 - name: github.com/uber-go/tally - version: be9e53c77349ae2dd4b8c03a6dc20ed9a88b9927 + version: 95078a8f10668bd1fa73ae46761cdc58d25436b8 subpackages: - m3 - m3/customtransports @@ -81,7 +81,7 @@ imports: - thrift-gen/zipkincore - utils - name: github.com/uber/jaeger-lib - version: 5b29ee594f76a8f6a822c18b02ef985d68ddd991 + version: 3b2a9ad2a045881ab7a0f81d465be54c8292ee4f subpackages: - metrics - metrics/tally diff --git a/glide.yaml b/glide.yaml index dd222c66c..39fcc85a6 100644 --- a/glide.yaml +++ b/glide.yaml @@ -47,3 +47,4 @@ import: - package: github.com/stretchr/testify version: f6abca593680b2315d2075e0f5e2a9751e3f431a - package: github.com/xeipuuv/gojsonschema + version: 3f523f4c14b6e925da10475eb0447c2f28614aac