You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/09/11 02:51:11 UTC
[apisix-dashboard] branch master updated: feat: support ungroup in
manager api (#460)
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new 66709c4 feat: support ungroup in manager api (#460)
66709c4 is described below
commit 66709c48749305608c33047af1ba10b3cc602cc1
Author: liuxiran <be...@126.com>
AuthorDate: Fri Sep 11 10:51:03 2020 +0800
feat: support ungroup in manager api (#460)
* feat: support ungroup in manager api
* fix: synchronize route group to route
* fix: update test case
---
api/errno/error.go | 1 +
api/route/route.go | 34 +++++++---
api/route/route_group_test.go | 92 ++++++++++++++++++++++----
api/route/route_test.go | 143 ++++++++++++++++++++++++++++++++++++++++
api/service/route_group.go | 20 +++++-
api/service/route_group_test.go | 120 +++++++++++++++++++++++++++++++++
6 files changed, 389 insertions(+), 21 deletions(-)
diff --git a/api/errno/error.go b/api/errno/error.go
index 68f313d..1004085 100644
--- a/api/errno/error.go
+++ b/api/errno/error.go
@@ -57,6 +57,7 @@ var (
DBRouteUpdateError = Message{"010206", "Route update failed: %s", 500}
DBRouteDeleteError = Message{"010207", "Route deletion failed: %s", 500}
DBRouteReduplicateError = Message{"010208", "Route name is reduplicate : %s", 400}
+ SetRouteUngroupError = Message{"010209", "Set route ungroup err", 500}
// 03 plugins
ApisixPluginListError = Message{"010301", "find APISIX plugin list failed: %s", 500}
diff --git a/api/route/route.go b/api/route/route.go
index b6ace35..5be339f 100644
--- a/api/route/route.go
+++ b/api/route/route.go
@@ -201,12 +201,17 @@ func updateRoute(c *gin.Context) {
}
routeGroup := &service.RouteGroupDao{}
isCreateGroup := false
+ isUngroup := false
if len(strings.Trim(routeRequest.RouteGroupId, "")) == 0 {
- isCreateGroup = true
- routeGroup.ID = uuid.NewV4()
- // create route group
- routeGroup.Name = routeRequest.RouteGroupName
- routeRequest.RouteGroupId = routeGroup.ID.String()
+ if len(strings.Trim(routeRequest.RouteGroupName, "")) > 0 {
+ isCreateGroup = true
+ routeGroup.ID = uuid.NewV4()
+ // create route group
+ routeGroup.Name = routeRequest.RouteGroupName
+ routeRequest.RouteGroupId = routeGroup.ID.String()
+ } else {
+ isUngroup = true
+ }
}
logger.Info(routeRequest.Plugins)
db := conf.DB()
@@ -253,6 +258,15 @@ func updateRoute(c *gin.Context) {
}
}
}
+ if isUngroup {
+ if err := tx.Model(&service.Route{}).Where("id = ?", rid).Update(map[string]interface{}{"route_group_id": "", "route_group_name": ""}).Error; err != nil {
+ tx.Rollback()
+ e := errno.FromMessage(errno.SetRouteUngroupError)
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ }
+ }
if err := tx.Commit().Error; err == nil {
// update content_admin_api
if rd, err := service.ToRoute(routeRequest, arr, uuid.FromStringOrNil(rid), resp); err != nil {
@@ -343,11 +357,13 @@ func createRoute(c *gin.Context) {
routeGroup := &service.RouteGroupDao{}
isCreateGroup := false
if len(strings.Trim(routeRequest.RouteGroupId, "")) == 0 {
- isCreateGroup = true
- routeGroup.ID = uuid.NewV4()
// create route group
- routeGroup.Name = routeRequest.RouteGroupName
- routeRequest.RouteGroupId = routeGroup.ID.String()
+ if len(strings.Trim(routeRequest.RouteGroupName, "")) > 0 {
+ isCreateGroup = true
+ routeGroup.ID = uuid.NewV4()
+ routeGroup.Name = routeRequest.RouteGroupName
+ routeRequest.RouteGroupId = routeGroup.ID.String()
+ }
}
logger.Info(routeRequest.Plugins)
db := conf.DB()
diff --git a/api/route/route_group_test.go b/api/route/route_group_test.go
index ce939db..9b6f0ff 100644
--- a/api/route/route_group_test.go
+++ b/api/route/route_group_test.go
@@ -17,45 +17,115 @@
package route
import (
+ "github.com/apisix/manager-api/conf"
+ "github.com/apisix/manager-api/service"
"net/http"
"testing"
)
-func TestRouteGroupCurd(t *testing.T) {
+func TestCreateRouteGroup(t *testing.T) {
// create ok
handler.
Post(uriPrefix+"/routegroups").
Header("Authorization", token).
JSON(`{
- "name": "routegroup_test",
+ "name": "create_route_group_test",
"description": "test description"
}`).
Expect(t).
Status(http.StatusOK).
End()
+}
- //c1, _ := service.GetConsumerByUserName("e2e_test_consumer1")
- id := "8954a39b-330e-4b85-89f5-d1bbfd785b5b"
- //update ok
+func TestDuplicateGroupName(t *testing.T) {
+ // duplicate name
handler.
- Put(uriPrefix+"/routegroups/"+id).
+ Post(uriPrefix+"/routegroups").
Header("Authorization", token).
JSON(`{
- "name": "routegroup_test2",
+ "name": "create_route_group_test",
"description": "test description"
}`).
Expect(t).
- Status(http.StatusOK).
+ Status(http.StatusInternalServerError).
End()
- // duplicate username
+}
+
+func TestUpdateRouteGroup(t *testing.T) {
+ routeGroup, _ := getRouteGroupByName("create_route_group_test")
+ //update ok
handler.
- Post(uriPrefix+"/routegroups").
+ Put(uriPrefix+"/routegroups/"+routeGroup.ID.String()).
Header("Authorization", token).
JSON(`{
- "name": "routegroup_test",
+ "name": "update_route_group_test",
"description": "test description"
}`).
Expect(t).
+ Status(http.StatusOK).
+ End()
+}
+
+func TestDeleteRouteGroupHasRoutes(t *testing.T) {
+ routeGroup, _ := getRouteGroupByName("update_route_group_test")
+ // create route
+ handler.Post(uriPrefix+"/routes").
+ Header("Authorization", token).
+ JSON(`{
+ "name":"api-test-for-delete-group",
+ "desc":"api-test",
+ "priority":0,
+ "protocols":["http"],
+ "hosts":["test.com"],
+ "paths":["/*"],
+ "methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
+ "status":false,
+ "upstream_protocol":"keep",
+ "plugins":{},
+ "uris":["/*"],
+ "vars":[],
+ "upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
+ "timeout":{"connect":6000,"send":6000,"read":6000}},
+ "upstream_header":{},
+ "route_group_id":"` + routeGroup.ID.String() + `",
+ "route_group_name":"` + routeGroup.Name + `"
+}`).Expect(t).
+ Status(http.StatusOK).
+ End()
+ // delete fail
+ handler.
+ Delete(uriPrefix+"/routegroups/"+routeGroup.ID.String()).
+ Header("Authorization", token).
+ Expect(t).
Status(http.StatusInternalServerError).
End()
+ // get api-test-for-group
+ route, _ := getRouteByName("api-test-for-delete-group")
+ // delete route
+ handler.
+ Delete(uriPrefix+"/routes/"+route.ID.String()).
+ Header("Authorization", token).
+ Expect(t).
+ Status(http.StatusOK).
+ End()
+}
+
+func TestDeleteRouteGroup(t *testing.T) {
+ routeGroup, _ := getRouteGroupByName("update_route_group_test")
+ // delete ok
+ handler.
+ Delete(uriPrefix+"/routegroups/"+routeGroup.ID.String()).
+ Header("Authorization", token).
+ Expect(t).
+ Status(http.StatusOK).
+ End()
+}
+
+func getRouteGroupByName(name string) (*service.RouteGroupDao, error) {
+ db := conf.DB()
+ routeGroup := &service.RouteGroupDao{}
+ if err := db.Table("route_group").Where("name = ?", name).First(&routeGroup).Error; err != nil {
+ return nil, err
+ }
+ return routeGroup, nil
}
diff --git a/api/route/route_test.go b/api/route/route_test.go
new file mode 100644
index 0000000..97442c0
--- /dev/null
+++ b/api/route/route_test.go
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package route
+
+import (
+ "net/http"
+ "testing"
+ "github.com/apisix/manager-api/conf"
+ "github.com/apisix/manager-api/service"
+)
+
+func TestCreateRouteForUngroup(t *testing.T) {
+ // create route with no route group -- test ungroup
+ handler.Post(uriPrefix+"/routes").
+ Header("Authorization", token).
+ JSON(`{
+ "name":"api-test-no-group",
+ "desc":"api-test-no-group",
+ "priority":0,
+ "protocols":["http"],
+ "hosts":["test.com"],
+ "paths":["/*"],
+ "methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
+ "status":false,
+ "upstream_protocol":"keep",
+ "plugins":{},
+ "uris":["/*"],
+ "vars":[],
+ "upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
+ "timeout":{"connect":6000,"send":6000,"read":6000}},
+ "upstream_header":{},
+ "route_group_id":"",
+ "route_group_name":""
+}`).Expect(t).
+ Status(http.StatusOK).
+ End()
+}
+
+func TestUpdateRouteWithCreateRouteGroup(t *testing.T) {
+ route, _ := getRouteByName("api-test-no-group")
+
+ // update route for create route group
+ handler.Put(uriPrefix+"/routes/"+route.ID.String()).
+ Header("Authorization", token).
+ JSON(`{
+ "name":"api-test-no-group",
+ "desc":"api-test-no-group",
+ "priority":0,
+ "protocols":["http"],
+ "hosts":["test.com"],
+ "paths":["/*"],
+ "methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
+ "status":false,
+ "upstream_protocol":"keep",
+ "plugins":{},
+ "uris":["/*"],
+ "vars":[],
+ "upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
+ "timeout":{"connect":6000,"send":6000,"read":6000}},
+ "upstream_header":{},
+ "route_group_id":"",
+ "route_group_name":"route-update-test-create-group"
+}`).Expect(t).
+ Status(http.StatusOK).
+ End()
+}
+
+func TestCreateRouteWithCreateNewGroup(t *testing.T) {
+ // create route with new route group
+ handler.Post(uriPrefix+"/routes").
+ Header("Authorization", token).
+ JSON(`{
+ "name":"api-test-new-group",
+ "desc":"api-test-new-group",
+ "priority":0,
+ "protocols":["http"],
+ "hosts":["test.com"],
+ "paths":["/*"],
+ "methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
+ "status":false,
+ "upstream_protocol":"keep",
+ "plugins":{},
+ "uris":["/*"],
+ "vars":[],
+ "upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
+ "timeout":{"connect":6000,"send":6000,"read":6000}},
+ "upstream_header":{},
+ "route_group_id":"",
+ "route_group_name":"route-create-test-create-group"
+}`).Expect(t).
+ Status(http.StatusOK).
+ End()
+}
+
+func TestCreateRouteWithDuplicateGroupName(t *testing.T) {
+ // create route with duplicate route group name
+ handler.Post(uriPrefix+"/routes").
+ Header("Authorization", token).
+ JSON(`{
+ "name":"api-test",
+ "desc":"api-test",
+ "priority":0,
+ "protocols":["http"],
+ "hosts":["test.com"],
+ "paths":["/*"],
+ "methods":["GET","HEAD","POST","PUT","DELETE","OPTIONS","PATCH"],
+ "status":false,
+ "upstream_protocol":"keep",
+ "plugins":{},
+ "uris":["/*"],
+ "vars":[],
+ "upstream":{"type":"roundrobin","nodes":{"127.0.0.1:443":1},
+ "timeout":{"connect":6000,"send":6000,"read":6000}},
+ "upstream_header":{},
+ "route_group_id":"",
+ "route_group_name":"route-create-test-create-group"
+}`).Expect(t).
+ Status(http.StatusInternalServerError).
+ End()
+}
+
+func getRouteByName(name string) (*service.Route, error) {
+ db := conf.DB()
+ route := &service.Route{}
+ if err := db.Table("routes").Where("name = ?", name).First(&route).Error; err != nil {
+ return nil, err
+ }
+ return route, nil
+}
diff --git a/api/service/route_group.go b/api/service/route_group.go
index b016883..8eb9a4d 100644
--- a/api/service/route_group.go
+++ b/api/service/route_group.go
@@ -66,7 +66,25 @@ func (rd *RouteGroupDao) GetRouteGroupList(routeGroupList *[]RouteGroupDao, sear
func (rd *RouteGroupDao) UpdateRouteGroup() error {
db := conf.DB()
- return db.Model(&RouteGroupDao{}).Update(rd).Error
+ tx := db.Begin()
+ defer func() {
+ if r := recover(); r != nil {
+ tx.Rollback()
+ }
+ }()
+ if err := tx.Model(&RouteGroupDao{}).Update(rd).Error; err != nil {
+ tx.Rollback()
+ return err
+ }
+ if err := tx.Table("routes").Where("route_group_id = ?", rd.ID.String()).Update("route_group_name", rd.Name).Error; err != nil {
+ tx.Rollback()
+ return err
+ }
+ if err := tx.Commit().Error; err != nil {
+ tx.Rollback()
+ return err
+ }
+ return nil
}
func (rd *RouteGroupDao) DeleteRouteGroup() error {
diff --git a/api/service/route_group_test.go b/api/service/route_group_test.go
new file mode 100644
index 0000000..cb656b3
--- /dev/null
+++ b/api/service/route_group_test.go
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package service
+
+import (
+ "testing"
+
+ uuid "github.com/satori/go.uuid"
+ "github.com/stretchr/testify/assert"
+)
+
+var gid = uuid.NewV4()
+var gid2 = uuid.NewV4()
+
+func TestCreateRouteGroup(t *testing.T) {
+ routeGroup := &RouteGroupDao{
+ Base: Base{},
+ Name: "route_group_test",
+ Description: "route_group_test",
+ }
+ routeGroup.ID = gid
+ // create ok
+ err := routeGroup.CreateRouteGroup()
+ as := assert.New(t)
+ as.Nil(err)
+}
+
+func TestGetRouteGroup(t *testing.T) {
+ // get group ok
+ as := assert.New(t)
+ getGroup := &RouteGroupDao{}
+ err, i := getGroup.FindRouteGroup(gid.String())
+ as.Nil(err)
+ as.Equal("route_group_test", getGroup.Name)
+ as.Equal(1, i)
+}
+
+func TestRouteGroupNameDuplicate(t *testing.T) {
+ // name duplicate
+ as := assert.New(t)
+ routeGroup2 := &RouteGroupDao{
+ Base: Base{},
+ Name: "route_group_test",
+ Description: "route_group_test",
+ }
+ routeGroup2.ID = gid2
+ err := routeGroup2.CreateRouteGroup()
+ as.NotNil(err)
+ // ok
+ routeGroup2.Name = "route_group_test2"
+ err = routeGroup2.CreateRouteGroup()
+ as.Nil(err)
+}
+
+func TestGetRouteGupList(t *testing.T) {
+ as := assert.New(t)
+ // list ok
+ routeGroups := []RouteGroupDao{}
+ routeGroup := &RouteGroupDao{}
+ err, i3 := routeGroup.GetRouteGroupList(&routeGroups, "", 1, 2)
+ as.Nil(err)
+ as.Equal(true, i3 >= 2)
+ as.Equal(2, len(routeGroups))
+}
+
+func TestUpdateRouteGroup(t *testing.T) {
+ as := assert.New(t)
+ // update ok
+ routeGroup := &RouteGroupDao{
+ Base: Base{},
+ Name: "route_group_test_update",
+ Description: "route_group_test_update",
+ }
+ routeGroup.ID = gid
+ err := routeGroup.UpdateRouteGroup()
+ as.Nil(err)
+}
+
+func TestDeleteRouteGroup(t *testing.T) {
+ as := assert.New(t)
+ routeGroup := &RouteGroupDao{
+ Base: Base{},
+ Name: "route_group_test_update",
+ Description: "route_group_test_update",
+ }
+ routeGroup.ID = gid
+ // delete ok
+ err := routeGroup.DeleteRouteGroup()
+ as.Nil(err)
+
+ deleteGroup := &RouteGroupDao{}
+ err, i2 := deleteGroup.FindRouteGroup(gid.String())
+ as.Nil(err)
+ as.Equal("", deleteGroup.Name)
+ as.Equal(0, i2)
+
+ routeGroup2 := &RouteGroupDao{
+ Base: Base{},
+ Name: "route_group_test",
+ Description: "route_group_test",
+ }
+ routeGroup2.ID = gid2
+ err = routeGroup2.DeleteRouteGroup()
+ as.Nil(err)
+}