You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by vi...@apache.org on 2020/09/18 14:04:52 UTC

[apisix-dashboard] branch refactor updated (24c627a -> a5956e7)

This is an automated email from the ASF dual-hosted git repository.

vinci pushed a change to branch refactor
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git.


    from 24c627a  fmt project
     new dda1cb9  feat: add validator for generic store; add demo error
     new a5956e7  feat: upgrade droplet

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 api/go.mod                                |  6 ++-
 api/go.sum                                | 10 +++++
 api/internal/core/store/store.go          | 20 +++++++--
 api/internal/core/store/store_test.go     | 71 +++++++++++++++++++++++--------
 api/internal/core/store/test_case.json    | 19 +++++++++
 api/internal/core/store/validate.go       | 49 +++++++++++++++++++++
 api/internal/core/store/validate_test.go  | 51 ++++++++++++++++++++++
 api/internal/core/store/validator_mock.go | 24 +++++++++++
 api/internal/utils/consts/error.go        | 12 ++++++
 9 files changed, 239 insertions(+), 23 deletions(-)
 create mode 100644 api/internal/core/store/test_case.json
 create mode 100644 api/internal/core/store/validate.go
 create mode 100644 api/internal/core/store/validate_test.go
 create mode 100644 api/internal/core/store/validator_mock.go
 create mode 100644 api/internal/utils/consts/error.go


[apisix-dashboard] 02/02: feat: upgrade droplet

Posted by vi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vinci pushed a commit to branch refactor
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git

commit a5956e72a6cfa69f843a0ce5fe421382af725765
Author: ShiningRush <27...@qq.com>
AuthorDate: Fri Sep 18 22:04:39 2020 +0800

    feat: upgrade droplet
---
 api/go.mod                         | 2 +-
 api/go.sum                         | 2 ++
 api/internal/core/store/store.go   | 1 -
 api/internal/utils/consts/error.go | 2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/api/go.mod b/api/go.mod
index af5cb74..1c935ff 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -17,7 +17,7 @@ require (
 	github.com/jinzhu/gorm v1.9.12
 	github.com/magiconair/properties v1.8.1
 	github.com/satori/go.uuid v1.2.0
-	github.com/shiningrush/droplet v0.1.1
+	github.com/shiningrush/droplet v0.1.2
 	github.com/shiningrush/droplet/wrapper/gin v0.1.0
 	github.com/sirupsen/logrus v1.6.0
 	github.com/spf13/viper v1.7.1
diff --git a/api/go.sum b/api/go.sum
index 7f9aa90..50b3cdf 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -278,6 +278,8 @@ github.com/shiningrush/droplet v0.1.0 h1:Lk/nzfouI8Xqv9VtzNZZISwTVxWeXmEd9IlgIZw
 github.com/shiningrush/droplet v0.1.0/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M=
 github.com/shiningrush/droplet v0.1.1 h1:x+69JP60jzq6ROmsDooNhVSX8jhwFEmjBnryVvCHgjc=
 github.com/shiningrush/droplet v0.1.1/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M=
+github.com/shiningrush/droplet v0.1.2 h1:nGE6Ii8Hgra6UQ6lr4jvkvFuSsmg3AASf+KCF8wQgxY=
+github.com/shiningrush/droplet v0.1.2/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M=
 github.com/shiningrush/droplet/wrapper/gin v0.1.0 h1:eKUtuInaz8BH9dwjDnpdnP29iH7bhaB0NIOF9tL7nFM=
 github.com/shiningrush/droplet/wrapper/gin v0.1.0/go.mod h1:ZJu+sCRrVXn5Pg618c1KK3Ob2UiXGuPM1ROx5uMM9YQ=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
diff --git a/api/internal/core/store/store.go b/api/internal/core/store/store.go
index 2d199d7..7296082 100644
--- a/api/internal/core/store/store.go
+++ b/api/internal/core/store/store.go
@@ -139,7 +139,6 @@ func (s *GenericStore) List(input ListInput) (*ListOutput, error) {
 			output.Rows = ret[skipCount:]
 			return output, nil
 		}
-
 		output.Rows = ret[skipCount:endIdx]
 	}
 
diff --git a/api/internal/utils/consts/error.go b/api/internal/utils/consts/error.go
index 7abee58..4f8f1d4 100644
--- a/api/internal/utils/consts/error.go
+++ b/api/internal/utils/consts/error.go
@@ -7,6 +7,6 @@ const (
 )
 
 var (
-  // base error please refer to github.com/shiningrush/droplet/data, such as data.ErrNotFound, data.ErrConflicted
+	// base error please refer to github.com/shiningrush/droplet/data, such as data.ErrNotFound, data.ErrConflicted
 	ErrDemoBiz = data.BaseError{Code: ErrCodeDemoBiz, Message: "this is just a demo error"}
 )


[apisix-dashboard] 01/02: feat: add validator for generic store; add demo error

Posted by vi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vinci pushed a commit to branch refactor
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git

commit dda1cb9e14ac0eefe17af1d29e0677596752d061
Author: ShiningRush <27...@qq.com>
AuthorDate: Fri Sep 18 21:51:52 2020 +0800

    feat: add validator for generic store; add demo error
---
 api/go.mod                                |  6 ++-
 api/go.sum                                |  8 ++++
 api/internal/core/store/store.go          | 19 +++++++--
 api/internal/core/store/store_test.go     | 71 +++++++++++++++++++++++--------
 api/internal/core/store/test_case.json    | 19 +++++++++
 api/internal/core/store/validate.go       | 49 +++++++++++++++++++++
 api/internal/core/store/validate_test.go  | 51 ++++++++++++++++++++++
 api/internal/core/store/validator_mock.go | 24 +++++++++++
 api/internal/utils/consts/error.go        | 12 ++++++
 9 files changed, 237 insertions(+), 22 deletions(-)

diff --git a/api/go.mod b/api/go.mod
index 9d230c1..af5cb74 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -15,16 +15,18 @@ require (
 	github.com/gogo/protobuf v1.3.1 // indirect
 	github.com/google/uuid v1.1.2 // indirect
 	github.com/jinzhu/gorm v1.9.12
+	github.com/magiconair/properties v1.8.1
 	github.com/satori/go.uuid v1.2.0
-	github.com/shiningrush/droplet v0.1.0
+	github.com/shiningrush/droplet v0.1.1
 	github.com/shiningrush/droplet/wrapper/gin v0.1.0
 	github.com/sirupsen/logrus v1.6.0
 	github.com/spf13/viper v1.7.1
 	github.com/steinfletcher/apitest v1.4.10 // indirect
 	github.com/stretchr/testify v1.6.1
 	github.com/tidwall/gjson v1.6.0
+	github.com/xeipuuv/gojsonschema v1.2.0
 	go.etcd.io/etcd v3.3.25+incompatible
-	go.uber.org/zap v1.16.0 // indirect
+	go.uber.org/zap v1.16.0
 	golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
 	golang.org/x/sys v0.0.0-20200915084602-288bc346aa39 // indirect
 	golang.org/x/text v0.3.3 // indirect
diff --git a/api/go.sum b/api/go.sum
index e99f700..7f9aa90 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -276,6 +276,8 @@ github.com/shiningrush/droplet v0.0.0-20191118073048-00b06fe19ce4 h1:p2mP/ZZegqn
 github.com/shiningrush/droplet v0.0.0-20191118073048-00b06fe19ce4/go.mod h1:E/th13n/wtPi+Cj2f0hAAEFeT3gb5xsS6Ob4WRrdxdM=
 github.com/shiningrush/droplet v0.1.0 h1:Lk/nzfouI8Xqv9VtzNZZISwTVxWeXmEd9IlgIZwU9IA=
 github.com/shiningrush/droplet v0.1.0/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M=
+github.com/shiningrush/droplet v0.1.1 h1:x+69JP60jzq6ROmsDooNhVSX8jhwFEmjBnryVvCHgjc=
+github.com/shiningrush/droplet v0.1.1/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M=
 github.com/shiningrush/droplet/wrapper/gin v0.1.0 h1:eKUtuInaz8BH9dwjDnpdnP29iH7bhaB0NIOF9tL7nFM=
 github.com/shiningrush/droplet/wrapper/gin v0.1.0/go.mod h1:ZJu+sCRrVXn5Pg618c1KK3Ob2UiXGuPM1ROx5uMM9YQ=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -324,6 +326,12 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
 github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
 github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
+github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
diff --git a/api/internal/core/store/store.go b/api/internal/core/store/store.go
index f9d6a47..2d199d7 100644
--- a/api/internal/core/store/store.go
+++ b/api/internal/core/store/store.go
@@ -20,9 +20,10 @@ type GenericStore struct {
 }
 
 type GenericStoreOption struct {
-	BasePath string
-	ObjType  reflect.Type
-	KeyFunc  func(obj interface{}) string
+	BasePath  string
+	ObjType   reflect.Type
+	KeyFunc   func(obj interface{}) string
+	Validator Validator
 }
 
 func NewGenericStore(opt GenericStoreOption) (*GenericStore, error) {
@@ -146,6 +147,12 @@ func (s *GenericStore) List(input ListInput) (*ListOutput, error) {
 }
 
 func (s *GenericStore) Create(ctx context.Context, obj interface{}) error {
+	if s.opt.Validator != nil {
+		if err := s.opt.Validator.Validate(obj); err != nil {
+			return err
+		}
+	}
+
 	key := s.opt.KeyFunc(obj)
 	if key == "" {
 		return fmt.Errorf("key is required")
@@ -167,6 +174,12 @@ func (s *GenericStore) Create(ctx context.Context, obj interface{}) error {
 }
 
 func (s *GenericStore) Update(ctx context.Context, obj interface{}) error {
+	if s.opt.Validator != nil {
+		if err := s.opt.Validator.Validate(obj); err != nil {
+			return err
+		}
+	}
+
 	key := s.opt.KeyFunc(obj)
 	if key == "" {
 		return fmt.Errorf("key is required")
diff --git a/api/internal/core/store/store_test.go b/api/internal/core/store/store_test.go
index 5d295a1..4895258 100644
--- a/api/internal/core/store/store_test.go
+++ b/api/internal/core/store/store_test.go
@@ -399,13 +399,14 @@ func TestGenericStore_List(t *testing.T) {
 
 func TestGenericStore_Create(t *testing.T) {
 	tests := []struct {
-		caseDesc  string
-		giveStore *GenericStore
-		giveObj   *TestStruct
-		giveErr   error
-		wantKey   string
-		wantStr   string
-		wantErr   error
+		caseDesc        string
+		giveStore       *GenericStore
+		giveObj         *TestStruct
+		giveErr         error
+		giveValidateErr error
+		wantKey         string
+		wantStr         string
+		wantErr         error
 	}{
 		{
 			caseDesc: "sanity",
@@ -462,10 +463,25 @@ func TestGenericStore_Create(t *testing.T) {
 			},
 			wantErr: fmt.Errorf("key: test1 is conflicted"),
 		},
+		{
+			caseDesc: "validate failed",
+			giveObj: &TestStruct{
+				Field1: "test1",
+				Field2: "test2",
+			},
+			giveStore: &GenericStore{
+				cache: map[string]interface{}{
+					"test1": struct{}{},
+				},
+				opt: GenericStoreOption{},
+			},
+			giveValidateErr: fmt.Errorf("validate failed"),
+			wantErr:         fmt.Errorf("validate failed"),
+		},
 	}
 
 	for _, tc := range tests {
-		createCalled := false
+		createCalled, validateCalled := false, false
 		mStorage := &storage.MockInterface{}
 		mStorage.On("Create", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
 			createCalled = true
@@ -473,22 +489,34 @@ func TestGenericStore_Create(t *testing.T) {
 			assert.Equal(t, tc.wantStr, args[2], tc.caseDesc)
 		}).Return(tc.giveErr)
 
+		mValidator := &MockValidator{}
+		mValidator.On("Validate", mock.Anything).Run(func(args mock.Arguments) {
+			validateCalled = true
+			assert.Equal(t, tc.giveObj, args.Get(0), tc.caseDesc)
+		}).Return(tc.giveValidateErr)
+
 		tc.giveStore.Stg = mStorage
+		tc.giveStore.opt.Validator = mValidator
 		err := tc.giveStore.Create(context.TODO(), tc.giveObj)
+		assert.True(t, validateCalled, tc.caseDesc)
+		if err != nil {
+			assert.Equal(t, tc.wantErr, err, tc.caseDesc)
+			continue
+		}
 		assert.True(t, createCalled, tc.caseDesc)
-		assert.Equal(t, tc.wantErr, err, tc.caseDesc)
 	}
 }
 
 func TestGenericStore_Update(t *testing.T) {
 	tests := []struct {
-		caseDesc  string
-		giveStore *GenericStore
-		giveObj   *TestStruct
-		giveErr   error
-		wantKey   string
-		wantStr   string
-		wantErr   error
+		caseDesc        string
+		giveStore       *GenericStore
+		giveObj         *TestStruct
+		giveErr         error
+		giveValidateErr error
+		wantKey         string
+		wantStr         string
+		wantErr         error
 	}{
 		{
 			caseDesc: "sanity",
@@ -554,7 +582,7 @@ func TestGenericStore_Update(t *testing.T) {
 	}
 
 	for _, tc := range tests {
-		createCalled := false
+		createCalled, validateCalled := false, false
 		mStorage := &storage.MockInterface{}
 		mStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
 			createCalled = true
@@ -562,8 +590,17 @@ func TestGenericStore_Update(t *testing.T) {
 			assert.Equal(t, tc.wantStr, args[2], tc.caseDesc)
 		}).Return(tc.giveErr)
 
+		mValidator := &MockValidator{}
+		mValidator.On("Validate", mock.Anything).Run(func(args mock.Arguments) {
+			validateCalled = true
+			assert.Equal(t, tc.giveObj, args.Get(0), tc.caseDesc)
+		}).Return(tc.giveValidateErr)
+
 		tc.giveStore.Stg = mStorage
+		tc.giveStore.opt.Validator = mValidator
+
 		err := tc.giveStore.Update(context.TODO(), tc.giveObj)
+		assert.True(t, validateCalled, tc.caseDesc)
 		if err != nil {
 			assert.Equal(t, tc.wantErr, err, tc.caseDesc)
 			continue
diff --git a/api/internal/core/store/test_case.json b/api/internal/core/store/test_case.json
new file mode 100644
index 0000000..77f524b
--- /dev/null
+++ b/api/internal/core/store/test_case.json
@@ -0,0 +1,19 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "type": "object",
+  "properties": {
+    "name":  {
+      "type": "string",
+      "minLength": 10
+    },
+    "email": {
+      "type": "string",
+      "maxLength": 10
+    },
+    "age": {
+      "type": "integer",
+      "minimum": 0
+    }
+  },
+  "additionalProperties": false
+}
diff --git a/api/internal/core/store/validate.go b/api/internal/core/store/validate.go
new file mode 100644
index 0000000..1ee0960
--- /dev/null
+++ b/api/internal/core/store/validate.go
@@ -0,0 +1,49 @@
+package store
+
+import (
+	"errors"
+	"fmt"
+	"github.com/xeipuuv/gojsonschema"
+	"go.uber.org/zap/buffer"
+	"io/ioutil"
+)
+
+type Validator interface {
+	Validate(obj interface{}) error
+}
+type JsonSchemaValidator struct {
+	schema *gojsonschema.Schema
+}
+
+func NewJsonSchemaValidator(jsonPath string) (Validator, error) {
+	bs, err := ioutil.ReadFile(jsonPath)
+	if err != nil {
+		return nil, fmt.Errorf("get abs path failed: %w", err)
+	}
+	s, err := gojsonschema.NewSchema(gojsonschema.NewStringLoader(string(bs)))
+	if err != nil {
+		return nil, fmt.Errorf("new schema failed: %w", err)
+	}
+	return &JsonSchemaValidator{
+		schema: s,
+	}, nil
+}
+
+func (v *JsonSchemaValidator) Validate(obj interface{}) error {
+	ret, err := v.schema.Validate(gojsonschema.NewGoLoader(obj))
+	if err != nil {
+		return fmt.Errorf("validate failed: %w", err)
+	}
+
+	if !ret.Valid() {
+		errString := buffer.Buffer{}
+		for i, vErr := range ret.Errors() {
+			if i != 0 {
+				errString.AppendString("\n")
+			}
+			errString.AppendString(vErr.String())
+		}
+		return errors.New(errString.String())
+	}
+	return nil
+}
diff --git a/api/internal/core/store/validate_test.go b/api/internal/core/store/validate_test.go
new file mode 100644
index 0000000..f7d1ac9
--- /dev/null
+++ b/api/internal/core/store/validate_test.go
@@ -0,0 +1,51 @@
+package store
+
+import (
+	"fmt"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+type TestOjb struct {
+	Name  string `json:"name"`
+	Email string `json:"email"`
+	Age   int    `json:"age"`
+}
+
+func TestJsonSchemaValidator_Validate(t *testing.T) {
+	tests := []struct {
+		givePath        string
+		giveObj         interface{}
+		wantNewErr      error
+		wantValidateErr []error
+	}{
+		{
+			givePath: "./test_case.json",
+			giveObj: TestOjb{
+				Name:  "lessName",
+				Email: "too long name greater than 10",
+				Age:   12,
+			},
+			wantValidateErr: []error{
+				fmt.Errorf("name: String length must be greater than or equal to 10\nemail: String length must be less than or equal to 10"),
+				fmt.Errorf("email: String length must be less than or equal to 10\nname: String length must be greater than or equal to 10"),
+			},
+		},
+	}
+
+	for _, tc := range tests {
+		v, err := NewJsonSchemaValidator(tc.givePath)
+		if err != nil {
+			assert.Equal(t, tc.wantNewErr, err)
+			continue
+		}
+		err = v.Validate(tc.giveObj)
+		ret := false
+		for _, wantErr := range tc.wantValidateErr {
+			if wantErr.Error() == err.Error() {
+				ret = true
+			}
+		}
+		assert.True(t, ret)
+	}
+}
diff --git a/api/internal/core/store/validator_mock.go b/api/internal/core/store/validator_mock.go
new file mode 100644
index 0000000..643ba78
--- /dev/null
+++ b/api/internal/core/store/validator_mock.go
@@ -0,0 +1,24 @@
+// Code generated by mockery v1.0.0. DO NOT EDIT.
+
+package store
+
+import mock "github.com/stretchr/testify/mock"
+
+// MockValidator is an autogenerated mock type for the Validator type
+type MockValidator struct {
+	mock.Mock
+}
+
+// Validate provides a mock function with given fields: obj
+func (_m *MockValidator) Validate(obj interface{}) error {
+	ret := _m.Called(obj)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
+		r0 = rf(obj)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
diff --git a/api/internal/utils/consts/error.go b/api/internal/utils/consts/error.go
new file mode 100644
index 0000000..7abee58
--- /dev/null
+++ b/api/internal/utils/consts/error.go
@@ -0,0 +1,12 @@
+package consts
+
+import "github.com/shiningrush/droplet/data"
+
+const (
+	ErrCodeDemoBiz = 20000
+)
+
+var (
+  // base error please refer to github.com/shiningrush/droplet/data, such as data.ErrNotFound, data.ErrConflicted
+	ErrDemoBiz = data.BaseError{Code: ErrCodeDemoBiz, Message: "this is just a demo error"}
+)