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/07 09:27:57 UTC
[apisix-dashboard] branch master updated: Feat: manage api support
route group (#432)
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 316633b Feat: manage api support route group (#432)
316633b is described below
commit 316633b76638192709daf7e17de59b090fc43515
Author: liuxiran <be...@126.com>
AuthorDate: Mon Sep 7 17:27:47 2020 +0800
Feat: manage api support route group (#432)
* feat(manage-api): add new module route group
* feat(manager-api): add route suport routeGroup
* fix: update some code and lint errors
* fix: support to create new routeGroup while creating route
Co-authored-by: liuxiran <yo...@googl.com>
---
api/errno/error.go | 8 ++
api/route/base.go | 15 +--
api/route/route.go | 51 +++++++++-
api/route/route_group.go | 217 ++++++++++++++++++++++++++++++++++++++++++
api/route/route_group_test.go | 45 +++++++++
api/script/db/schema.sql | 14 ++-
api/service/route.go | 58 +++++++----
api/service/route_group.go | 137 ++++++++++++++++++++++++++
8 files changed, 517 insertions(+), 28 deletions(-)
diff --git a/api/errno/error.go b/api/errno/error.go
index 93180d8..68f313d 100644
--- a/api/errno/error.go
+++ b/api/errno/error.go
@@ -86,6 +86,14 @@ var (
ApisixConsumerDeleteError = Message{"010704", "APISIX Consumer delete failed", 500}
DuplicateUserName = Message{"010705", "Duplicate consumer username", 400}
+ // 08 routeGroup
+ RouteGroupRequestError = Message{"010801", "RouteGroup request parameters exception: %s", 400}
+ DBRouteGroupError = Message{"010802", "RouteGroup storage failure: %s", 500}
+ DBRouteGroupDeleteError = Message{"010803", "RouteGroup storage delete failed: %s", 500}
+ RouteGroupHasRoutesError = Message{"010804", "Route exist in this route group ", 500}
+ RouteGroupSelectRoutesError = Message{"010805", "RouteGroup select routes failed : %s", 500}
+ DuplicateRouteGroupName = Message{"010806", "RouteGroup name is duplicate : %s", 500}
+
// 99 authentication
AuthenticationUserError = Message{"019901", "username or password error", 401}
)
diff --git a/api/route/base.go b/api/route/base.go
index 1b48d4a..41f5a1c 100644
--- a/api/route/base.go
+++ b/api/route/base.go
@@ -17,13 +17,13 @@
package route
import (
- "github.com/gin-contrib/pprof"
- "github.com/gin-contrib/sessions"
- "github.com/gin-contrib/sessions/cookie"
- "github.com/gin-gonic/gin"
+ "github.com/gin-contrib/pprof"
+ "github.com/gin-contrib/sessions"
+ "github.com/gin-contrib/sessions/cookie"
+ "github.com/gin-gonic/gin"
- "github.com/apisix/manager-api/conf"
- "github.com/apisix/manager-api/filter"
+ "github.com/apisix/manager-api/conf"
+ "github.com/apisix/manager-api/filter"
)
func SetUpRouter() *gin.Engine {
@@ -35,7 +35,7 @@ func SetUpRouter() *gin.Engine {
r := gin.New()
store := cookie.NewStore([]byte("secret"))
r.Use(sessions.Sessions("session", store))
- r.Use(filter.CORS(), filter.Authentication(),filter.RequestId(), filter.RequestLogHandler(), filter.RecoverHandler())
+ r.Use(filter.CORS(), filter.Authentication(), filter.RequestId(), filter.RequestLogHandler(), filter.RecoverHandler())
AppendHealthCheck(r)
AppendAuthentication(r)
@@ -44,6 +44,7 @@ func SetUpRouter() *gin.Engine {
AppendPlugin(r)
AppendUpstream(r)
AppendConsumer(r)
+ AppendRouteGroup(r)
pprof.Register(r)
diff --git a/api/route/route.go b/api/route/route.go
index c86b437..b6ace35 100644
--- a/api/route/route.go
+++ b/api/route/route.go
@@ -20,6 +20,7 @@ import (
"encoding/json"
"net/http"
"strconv"
+ "strings"
"github.com/apisix/manager-api/conf"
"github.com/apisix/manager-api/errno"
@@ -101,11 +102,19 @@ func listRoute(c *gin.Context) {
db = db.Where("upstream_nodes like ? ", "%"+ip+"%")
isSearch = false
}
+ if rgid, exist := c.GetQuery("route_group_id"); exist {
+ db = db.Where("route_group_id = ?", rgid)
+ isSearch = false
+ }
+ if rgName, exist := c.GetQuery("route_group_name"); exist {
+ db = db.Where("route_group_name like ?", "%"+rgName+"%")
+ isSearch = false
+ }
// search
if isSearch {
if search, exist := c.GetQuery("search"); exist {
s := "%" + search + "%"
- db = db.Where("name like ? or description like ? or hosts like ? or uris like ? or upstream_nodes like ? ", s, s, s, s, s)
+ db = db.Where("name like ? or description like ? or hosts like ? or uris like ? or upstream_nodes like ? or route_group_id = ? or route_group_name like ?", s, s, s, s, s, search, s)
}
}
// mysql
@@ -190,6 +199,15 @@ func updateRoute(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
return
}
+ 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()
+ }
logger.Info(routeRequest.Plugins)
db := conf.DB()
arr := service.ToApisixRequest(routeRequest)
@@ -205,6 +223,15 @@ func updateRoute(c *gin.Context) {
}
}()
logger.Info(rd)
+ if isCreateGroup {
+ if err := tx.Model(&service.RouteGroupDao{}).Create(routeGroup).Error; err != nil {
+ tx.Rollback()
+ e := errno.FromMessage(errno.DuplicateRouteGroupName, routeGroup.Name)
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ }
+ }
if err := tx.Model(&service.Route{}).Update(rd).Error; err != nil {
// rollback
tx.Rollback()
@@ -288,6 +315,8 @@ func findRoute(c *gin.Context) {
}
result.Script = script
+ result.RouteGroupId = route.RouteGroupId
+ result.RouteGroupName = route.RouteGroupName
resp, _ := json.Marshal(result)
c.Data(http.StatusOK, service.ContentType, resp)
}
@@ -311,6 +340,15 @@ func createRoute(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
return
}
+ 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()
+ }
logger.Info(routeRequest.Plugins)
db := conf.DB()
arr := service.ToApisixRequest(routeRequest)
@@ -326,7 +364,16 @@ func createRoute(c *gin.Context) {
}
}()
logger.Info(rd)
- if err := tx.Create(rd).Error; err != nil {
+ if isCreateGroup {
+ if err := tx.Model(&service.RouteGroupDao{}).Create(routeGroup).Error; err != nil {
+ tx.Rollback()
+ e := errno.FromMessage(errno.DuplicateRouteGroupName, routeGroup.Name)
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ }
+ }
+ if err := tx.Model(&service.Route{}).Create(rd).Error; err != nil {
// rollback
tx.Rollback()
e := errno.FromMessage(errno.DBRouteCreateError, err.Error())
diff --git a/api/route/route_group.go b/api/route/route_group.go
new file mode 100644
index 0000000..bfe138a
--- /dev/null
+++ b/api/route/route_group.go
@@ -0,0 +1,217 @@
+package route
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strconv"
+
+ "github.com/apisix/manager-api/conf"
+ "github.com/apisix/manager-api/errno"
+ "github.com/apisix/manager-api/service"
+ "github.com/gin-gonic/gin"
+ uuid "github.com/satori/go.uuid"
+)
+
+func AppendRouteGroup(r *gin.Engine) *gin.Engine {
+ r.POST("/apisix/admin/routegroups", createRouteGroup)
+ r.GET("/apisix/admin/routegroups/:gid", findRouteGroup)
+ r.GET("/apisix/admin/routegroups", listRouteGroup)
+ r.GET("/apisix/admin/names/routegroups", listRouteGroupName)
+ r.PUT("/apisix/admin/routegroups/:gid", updateRouteGroup)
+ r.DELETE("/apisix/admin/routegroups/:gid", deleteRouteGroup)
+ r.GET("/apisix/admin/notexist/routegroups", isRouteGroupExist)
+ return r
+}
+
+func isRouteGroupExist(c *gin.Context) {
+ if name, exist := c.GetQuery("name"); exist {
+ db := conf.DB()
+ db = db.Table("route_group")
+ exclude, exist := c.GetQuery("exclude")
+ if exist {
+ db = db.Where("name=? and id<>?", name, exclude)
+ } else {
+ db = db.Where("name=?", name)
+ }
+ var count int
+ if err := db.Count(&count).Error; err != nil {
+ e := errno.FromMessage(errno.RouteGroupRequestError, err.Error())
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ } else {
+ if count == 0 {
+ c.Data(http.StatusOK, service.ContentType, errno.Success())
+ return
+ } else {
+ e := errno.FromMessage(errno.DuplicateRouteGroupName, name)
+ c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
+ return
+ }
+ }
+ } else {
+ e := errno.FromMessage(errno.RouteGroupRequestError, "name is needed")
+ c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
+ return
+ }
+}
+
+func createRouteGroup(c *gin.Context) {
+ u4 := uuid.NewV4()
+ gid := u4.String()
+ // todo 参数校验
+ param, exist := c.Get("requestBody")
+ if !exist || len(param.([]byte)) < 1 {
+ e := errno.FromMessage(errno.RouteRequestError, "route_group create with no post data")
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
+ return
+ }
+ // trans params
+ rr := &service.RouteGroupRequest{}
+ if err := rr.Parse(param); err != nil {
+ e := errno.FromMessage(errno.RouteGroupRequestError, err.Error())
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
+ return
+ }
+ rr.Id = gid
+ fmt.Println(rr)
+ // mysql
+ if rd, err := service.Trans2RouteGroupDao(rr); err != nil {
+ c.AbortWithStatusJSON(http.StatusInternalServerError, err.Response())
+ return
+ } else {
+ if err := rd.CreateRouteGroup(); err != nil {
+ e := errno.FromMessage(errno.DBRouteGroupError, err.Error())
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ }
+ }
+ c.Data(http.StatusOK, service.ContentType, errno.Success())
+}
+
+func findRouteGroup(c *gin.Context) {
+ gid := c.Param("gid")
+ routeGroup := &service.RouteGroupDao{}
+ if err, count := routeGroup.FindRouteGroup(gid); err != nil {
+ e := errno.FromMessage(errno.RouteGroupRequestError, err.Error()+"route_group ID:"+gid)
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
+ return
+ } else {
+ if count < 1 {
+ e := errno.FromMessage(errno.RouteRequestError, " route_group ID: "+gid+" not exist")
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(e.Status, e.Response())
+ return
+ }
+ }
+ resp, _ := json.Marshal(routeGroup)
+ c.Data(http.StatusOK, service.ContentType, resp)
+}
+
+func listRouteGroup(c *gin.Context) {
+ size, _ := strconv.Atoi(c.Query("size"))
+ page, _ := strconv.Atoi(c.Query("page"))
+ if size == 0 {
+ size = 10
+ }
+ var s string
+
+ rd := &service.RouteGroupDao{}
+ routeGroupList := []service.RouteGroupDao{}
+ if search, exist := c.GetQuery("search"); exist && len(search) > 0 {
+ s = "%" + search + "%"
+ }
+ if err, count := rd.GetRouteGroupList(&routeGroupList, s, page, size); err != nil {
+ e := errno.FromMessage(errno.RouteGroupRequestError, err.Error())
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ } else {
+ result := &service.ListResponse{Count: count, Data: routeGroupList}
+ resp, _ := json.Marshal(result)
+ c.Data(http.StatusOK, service.ContentType, resp)
+ }
+}
+
+func listRouteGroupName(c *gin.Context) {
+ db := conf.DB()
+ routeGroupList := []service.RouteGroupDao{}
+ var count int
+ if err := db.Order("name").Table("route_group").Find(&routeGroupList).Count(&count).Error; err != nil {
+ e := errno.FromMessage(errno.RouteGroupRequestError, err.Error())
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ } else {
+ responseList := make([]*service.RouteGroupNameResponse, 0)
+ for _, r := range routeGroupList {
+ response, err := r.Parse2NameResponse()
+ if err == nil {
+ responseList = append(responseList, response)
+ }
+ }
+ result := &service.ListResponse{Count: count, Data: responseList}
+ resp, _ := json.Marshal(result)
+ c.Data(http.StatusOK, service.ContentType, resp)
+ }
+}
+
+func updateRouteGroup(c *gin.Context) {
+ // get params
+ gid := c.Param("gid")
+ param, exist := c.Get("requestBody")
+ if !exist || len(param.([]byte)) < 1 {
+ e := errno.FromMessage(errno.RouteRequestError, "route_group update with no post data")
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
+ return
+ }
+ // trans params
+ rr := &service.RouteGroupRequest{}
+ if err := rr.Parse(param); err != nil {
+ e := errno.FromMessage(errno.RouteGroupRequestError, err.Error())
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
+ return
+ }
+ rr.Id = gid
+ if ud, err := service.Trans2RouteGroupDao(rr); err != nil {
+ c.AbortWithStatusJSON(http.StatusInternalServerError, err.Response())
+ return
+ } else {
+ // mysql
+ if err2 := ud.UpdateRouteGroup(); err2 != nil {
+ e := errno.FromMessage(errno.DBRouteGroupError, err2.Error())
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ }
+ }
+ c.Data(http.StatusOK, service.ContentType, errno.Success())
+}
+
+func deleteRouteGroup(c *gin.Context) {
+ gid := c.Param("gid")
+ // 参数校验
+ routeGroup := &service.RouteGroupDao{}
+ if err := conf.DB().Table("route_group").Where("id=?", gid).First(&routeGroup).Error; err != nil {
+ e := errno.FromMessage(errno.RouteGroupRequestError, err.Error()+" route_group ID: "+gid)
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusBadRequest, e.Response())
+ return
+ }
+ // delete from mysql
+ routeGroup.ID = uuid.FromStringOrNil(gid)
+ if err := routeGroup.DeleteRouteGroup(); err != nil {
+ e := errno.FromMessage(errno.DBRouteGroupDeleteError, err.Error())
+ logger.Error(e.Msg)
+ c.AbortWithStatusJSON(http.StatusInternalServerError, e.Response())
+ return
+ }
+ c.Data(http.StatusOK, service.ContentType, errno.Success())
+}
diff --git a/api/route/route_group_test.go b/api/route/route_group_test.go
new file mode 100644
index 0000000..0500c8f
--- /dev/null
+++ b/api/route/route_group_test.go
@@ -0,0 +1,45 @@
+package route
+
+import (
+ "net/http"
+ "testing"
+)
+
+func TestRouteGroupCurd(t *testing.T) {
+ // create ok
+ handler.
+ Post(uriPrefix+"/routegroups").
+ Header("Authorization", token).
+ JSON(`{
+ "name": "routegroup_test",
+ "description": "test description"
+ }`).
+ Expect(t).
+ Status(http.StatusOK).
+ End()
+
+ //c1, _ := service.GetConsumerByUserName("e2e_test_consumer1")
+ id := "8954a39b-330e-4b85-89f5-d1bbfd785b5b"
+ //update ok
+ handler.
+ Put(uriPrefix+"/routegroups/"+id).
+ Header("Authorization", token).
+ JSON(`{
+ "name": "routegroup_test2",
+ "description": "test description"
+ }`).
+ Expect(t).
+ Status(http.StatusOK).
+ End()
+ // duplicate username
+ handler.
+ Post(uriPrefix+"/routegroups").
+ Header("Authorization", token).
+ JSON(`{
+ "name": "routegroup_test",
+ "description": "test description"
+ }`).
+ Expect(t).
+ Status(http.StatusInternalServerError).
+ End()
+}
diff --git a/api/script/db/schema.sql b/api/script/db/schema.sql
index b1db5a0..af83929 100644
--- a/api/script/db/schema.sql
+++ b/api/script/db/schema.sql
@@ -16,6 +16,8 @@ CREATE TABLE `routes` (
`content_admin_api` text,
`create_time` bigint(20),
`update_time` bigint(20),
+ `route_group_id` varchar(64) NOT NULL,
+ `route_group_name` varchar(64) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
@@ -56,4 +58,14 @@ CREATE TABLE `consumers` (
`update_time` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uni_username` (`username`)
-) DEFAULT CHARSET=utf8;
\ No newline at end of file
+) DEFAULT CHARSET=utf8;
+-- route_group
+CREATE TABLE `route_group` (
+ `id` varchar(64) NOT NULL unique,
+ `name` varchar(200) NOT NULL unique,
+ `description` varchar(200) DEFAULT NULL,
+ `create_time` bigint(20),
+ `update_time` bigint(20),
+
+ PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
diff --git a/api/service/route.go b/api/service/route.go
index 88cc16b..5a88af9 100644
--- a/api/service/route.go
+++ b/api/service/route.go
@@ -21,6 +21,7 @@ import (
"fmt"
"io/ioutil"
"os/exec"
+ "strings"
"time"
"github.com/apisix/manager-api/conf"
@@ -53,6 +54,13 @@ func (r *RouteRequest) Parse(body interface{}) error {
if r.Uris == nil || len(r.Uris) < 1 {
r.Uris = []string{"/*"}
}
+ if len(strings.Trim(r.RouteGroupId, "")) > 0 {
+ routeGroup := &RouteGroupDao{}
+ if err, _ := routeGroup.FindRouteGroup(r.RouteGroupId); err != nil {
+ return err
+ }
+ r.RouteGroupName = routeGroup.Name
+ }
}
return nil
}
@@ -72,6 +80,8 @@ func (rd *Route) Parse(r *RouteRequest, arr *ApisixRouteRequest) error {
//rd.Name = arr.Name
rd.Description = arr.Desc
rd.UpstreamId = r.UpstreamId
+ rd.RouteGroupId = r.RouteGroupId
+ rd.RouteGroupName = r.RouteGroupName
if content, err := json.Marshal(r); err != nil {
return err
} else {
@@ -180,6 +190,8 @@ type RouteRequest struct {
UpstreamHeader map[string]string `json:"upstream_header,omitempty"`
Plugins map[string]interface{} `json:"plugins"`
Script map[string]interface{} `json:"script"`
+ RouteGroupId string `json:"route_group_id"`
+ RouteGroupName string `json:"route_group_name"`
}
func (r *ApisixRouteResponse) Parse() (*RouteRequest, error) {
@@ -277,6 +289,7 @@ func (r *ApisixRouteResponse) Parse() (*RouteRequest, error) {
Redirect: redirect,
Upstream: o.Upstream,
UpstreamId: o.UpstreamId,
+ RouteGroupId: o.RouteGroupId,
UpstreamProtocol: upstreamProtocol,
UpstreamPath: upstreamPath,
UpstreamHeader: upstreamHeader,
@@ -388,17 +401,19 @@ type Node struct {
}
type Value struct {
- Id string `json:"id"`
- Name string `json:"name"`
- Desc string `json:"desc,omitempty"`
- Priority int64 `json:"priority"`
- Methods []string `json:"methods"`
- Uris []string `json:"uris"`
- Hosts []string `json:"hosts"`
- Vars [][]string `json:"vars"`
- Upstream *Upstream `json:"upstream,omitempty"`
- UpstreamId string `json:"upstream_id,omitempty"`
- Plugins map[string]interface{} `json:"plugins"`
+ Id string `json:"id"`
+ Name string `json:"name"`
+ Desc string `json:"desc,omitempty"`
+ Priority int64 `json:"priority"`
+ Methods []string `json:"methods"`
+ Uris []string `json:"uris"`
+ Hosts []string `json:"hosts"`
+ Vars [][]string `json:"vars"`
+ Upstream *Upstream `json:"upstream,omitempty"`
+ UpstreamId string `json:"upstream_id,omitempty"`
+ Plugins map[string]interface{} `json:"plugins"`
+ RouteGroupId string `json:"route_group_id"`
+ RouteGroupName string `json:"route_group_name"`
}
type Route struct {
@@ -413,17 +428,21 @@ type Route struct {
Content string `json:"content"`
Script string `json:"script"`
ContentAdminApi string `json:"content_admin_api"`
+ RouteGroupId string `json:"route_group_id"`
+ RouteGroupName string `json:"route_group_name"`
}
type RouteResponse struct {
Base
- Name string `json:"name"`
- Description string `json:"description,omitempty"`
- Hosts []string `json:"hosts,omitempty"`
- Uris []string `json:"uris,omitempty"`
- Upstream *Upstream `json:"upstream,omitempty"`
- UpstreamId string `json:"upstream_id,omitempty"`
- Priority int64 `json:"priority"`
+ Name string `json:"name"`
+ Description string `json:"description,omitempty"`
+ Hosts []string `json:"hosts,omitempty"`
+ Uris []string `json:"uris,omitempty"`
+ Upstream *Upstream `json:"upstream,omitempty"`
+ UpstreamId string `json:"upstream_id,omitempty"`
+ Priority int64 `json:"priority"`
+ RouteGroupId string `json:"route_group_id"`
+ RouteGroupName string `json:"route_group_name"`
}
type ListResponse struct {
@@ -437,6 +456,8 @@ func (rr *RouteResponse) Parse(r *Route) {
rr.Description = r.Description
rr.UpstreamId = r.UpstreamId
rr.Priority = r.Priority
+ rr.RouteGroupId = r.RouteGroupId
+ rr.RouteGroupName = r.RouteGroupName
// hosts
if len(r.Hosts) > 0 {
var hosts []string
@@ -575,6 +596,7 @@ func ToRoute(routeRequest *RouteRequest,
rd.ID = u4
// content_admin_api
if resp != nil {
+ resp.Node.Value.RouteGroupId = rd.RouteGroupId
if respStr, err := json.Marshal(resp); err != nil {
e := errno.FromMessage(errno.DBRouteCreateError, err.Error())
return nil, e
diff --git a/api/service/route_group.go b/api/service/route_group.go
new file mode 100644
index 0000000..b016883
--- /dev/null
+++ b/api/service/route_group.go
@@ -0,0 +1,137 @@
+/*
+ * 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 (
+ "encoding/json"
+ "github.com/apisix/manager-api/conf"
+ "github.com/apisix/manager-api/errno"
+ uuid "github.com/satori/go.uuid"
+)
+
+type RouteGroupDao struct {
+ Base
+ Name string `json:"name"`
+ Description string `json:"description,omitempty"`
+}
+
+func (RouteGroupDao) TableName() string {
+ return "route_group"
+}
+
+func (rd *RouteGroupDao) CreateRouteGroup() error {
+ return conf.DB().Create(&rd).Error
+}
+
+func (rd *RouteGroupDao) FindRouteGroup(id string) (error, int) {
+ var count int
+ if err := conf.DB().Table("route_group").Where("id=?", id).Count(&count).Error; err != nil {
+ return err, 0
+ }
+ conf.DB().Table("route_group").Where("id=?", id).First(&rd)
+ return nil, count
+}
+
+func (rd *RouteGroupDao) GetRouteGroupList(routeGroupList *[]RouteGroupDao, search string, page, size int) (error, int) {
+ db := conf.DB()
+ db = db.Table(rd.TableName())
+ if len(search) != 0 {
+ db = db.Where("name like ? or description like ? ", search, search)
+ }
+ var count int
+ if err := db.Order("update_time desc").Offset((page - 1) * size).Limit(size).Find(&routeGroupList).Error; err != nil {
+ return err, 0
+ } else {
+ if err := db.Count(&count).Error; err != nil {
+ return err, 0
+ }
+ return nil, count
+ }
+}
+
+func (rd *RouteGroupDao) UpdateRouteGroup() error {
+ db := conf.DB()
+ return db.Model(&RouteGroupDao{}).Update(rd).Error
+}
+
+func (rd *RouteGroupDao) DeleteRouteGroup() error {
+ if err, count := rd.FindRoute(); err != nil {
+ e := errno.FromMessage(errno.RouteGroupSelectRoutesError, err.Error())
+ logger.Error(e.Msg)
+ return e
+ } else {
+ if count > 0 {
+ e := errno.FromMessage(errno.RouteGroupHasRoutesError)
+ logger.Error(e.Msg)
+ return e
+ }
+ }
+ return conf.DB().Delete(&rd).Error
+}
+
+type RouteGroupNameResponse struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+}
+
+func (u *RouteGroupDao) Parse2NameResponse() (*RouteGroupNameResponse, error) {
+ // routeGroup
+ unr := &RouteGroupNameResponse{
+ ID: u.ID.String(),
+ Name: u.Name,
+ }
+ return unr, nil
+}
+
+type RouteGroupRequest struct {
+ Id string `json:"id,omitempty"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+}
+
+func (u *RouteGroupRequest) toJson() []byte {
+ res, _ := json.Marshal(&u)
+ return res
+}
+
+func (r *RouteGroupRequest) Parse(body interface{}) error {
+ if err := json.Unmarshal(body.([]byte), r); err != nil {
+ r = nil
+ return err
+ }
+ return nil
+}
+
+func Trans2RouteGroupDao(r *RouteGroupRequest) (*RouteGroupDao, *errno.ManagerError) {
+
+ u := &RouteGroupDao{
+ Name: r.Name,
+ Description: r.Description,
+ }
+ // id
+ u.ID = uuid.FromStringOrNil(r.Id)
+ return u, nil
+}
+
+func (r *RouteGroupDao) FindRoute() (error, int) {
+ var count int
+ if err := conf.DB().Table("routes").Where("route_group_id=?", r.ID).Count(&count).Error; err != nil {
+ return err, 0
+ }
+ return nil, count
+}