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 <[email protected]>
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)
+}

Reply via email to