615 lines
16 KiB
Go
615 lines
16 KiB
Go
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
|
//go:build plus
|
|
|
|
package nameservers
|
|
|
|
import (
|
|
"context"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models/nameservers"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
|
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
"github.com/iwind/TeaGo/types"
|
|
"sort"
|
|
)
|
|
|
|
// NSRouteService 线路相关服务
|
|
type NSRouteService struct {
|
|
services.BaseService
|
|
}
|
|
|
|
// CreateNSRoute 创建自定义线路
|
|
func (this *NSRouteService) CreateNSRoute(ctx context.Context, req *pb.CreateNSRouteRequest) (*pb.CreateNSRouteResponse, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var tx = this.NullTx()
|
|
|
|
if userId > 0 {
|
|
req.UserId = userId
|
|
|
|
// 暂时不允许在集群和域名下创建线路
|
|
req.NsClusterId = 0
|
|
req.NsDomainId = 0
|
|
}
|
|
|
|
// TODO 检查线路数限制
|
|
|
|
// 检查分类是否存在
|
|
if req.NsRouteCategoryId > 0 {
|
|
if userId > 0 {
|
|
err = nameservers.SharedNSRouteCategoryDAO.CheckUserCategory(tx, userId, req.NsRouteCategoryId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
exists, err := nameservers.SharedNSRouteCategoryDAO.Exist(tx, req.NsRouteCategoryId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !exists {
|
|
return nil, errors.New("route category id '" + types.String(req.NsRouteCategoryId) + "' not found")
|
|
}
|
|
}
|
|
} else {
|
|
req.NsRouteCategoryId = 0
|
|
}
|
|
|
|
routeId, err := nameservers.SharedNSRouteDAO.CreateRoute(tx, req.NsClusterId, req.NsDomainId, req.UserId, req.Name, req.RangesJSON, req.NsRouteCategoryId, req.Priority, req.IsPublic)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &pb.CreateNSRouteResponse{NsRouteId: routeId}, nil
|
|
}
|
|
|
|
// UpdateNSRoute 修改自定义线路
|
|
func (this *NSRouteService) UpdateNSRoute(ctx context.Context, req *pb.UpdateNSRouteRequest) (*pb.RPCSuccess, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var tx = this.NullTx()
|
|
|
|
// 检查权限
|
|
if userId > 0 {
|
|
err = nameservers.SharedNSRouteDAO.CheckUserRoute(tx, userId, req.NsRouteId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// 检查分类是否存在
|
|
if req.NsRouteCategoryId > 0 {
|
|
if userId > 0 {
|
|
err = nameservers.SharedNSRouteCategoryDAO.CheckUserCategory(tx, userId, req.NsRouteCategoryId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
exists, err := nameservers.SharedNSRouteCategoryDAO.Exist(tx, req.NsRouteCategoryId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !exists {
|
|
return nil, errors.New("route category id '" + types.String(req.NsRouteCategoryId) + "' not found")
|
|
}
|
|
}
|
|
} else {
|
|
req.NsRouteCategoryId = 0
|
|
}
|
|
|
|
err = nameservers.SharedNSRouteDAO.UpdateRoute(tx, req.NsRouteId, req.Name, req.RangesJSON, req.NsRouteCategoryId, req.Priority, req.IsPublic, req.IsOn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
// DeleteNSRoute 删除自定义线路
|
|
func (this *NSRouteService) DeleteNSRoute(ctx context.Context, req *pb.DeleteNSRouteRequest) (*pb.RPCSuccess, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var tx = this.NullTx()
|
|
|
|
// 检查权限
|
|
if userId > 0 {
|
|
err = nameservers.SharedNSRouteDAO.CheckUserRoute(tx, userId, req.NsRouteId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
err = nameservers.SharedNSRouteDAO.DisableNSRoute(tx, req.NsRouteId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
// FindNSRoute 获取单个自定义路线信息
|
|
func (this *NSRouteService) FindNSRoute(ctx context.Context, req *pb.FindNSRouteRequest) (*pb.FindNSRouteResponse, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var tx = this.NullTx()
|
|
|
|
// 检查权限
|
|
if userId > 0 {
|
|
err = nameservers.SharedNSRouteDAO.CheckUserRoute(tx, userId, req.NsRouteId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
route, err := nameservers.SharedNSRouteDAO.FindEnabledNSRoute(tx, req.NsRouteId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if route == nil {
|
|
return &pb.FindNSRouteResponse{NsRoute: nil}, nil
|
|
}
|
|
|
|
// 集群
|
|
var pbCluster *pb.NSCluster
|
|
if route.ClusterId > 0 {
|
|
cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(route.ClusterId))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if cluster != nil {
|
|
pbCluster = &pb.NSCluster{
|
|
Id: int64(cluster.Id),
|
|
IsOn: cluster.IsOn,
|
|
Name: cluster.Name,
|
|
}
|
|
}
|
|
}
|
|
|
|
// 域名
|
|
var pbDomain *pb.NSDomain
|
|
if route.DomainId > 0 {
|
|
domain, err := nameservers.SharedNSDomainDAO.FindEnabledNSDomain(tx, int64(route.DomainId))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if domain != nil {
|
|
pbDomain = &pb.NSDomain{
|
|
Id: int64(domain.Id),
|
|
Name: domain.Name,
|
|
IsOn: domain.IsOn,
|
|
}
|
|
}
|
|
}
|
|
|
|
// 分类
|
|
var pbCategory *pb.NSRouteCategory
|
|
if route.CategoryId > 0 {
|
|
category, err := nameservers.SharedNSRouteCategoryDAO.FindCategory(tx, int64(route.CategoryId))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if category != nil {
|
|
pbCategory = &pb.NSRouteCategory{
|
|
Id: int64(category.Id),
|
|
Name: category.Name,
|
|
IsOn: category.IsOn,
|
|
}
|
|
}
|
|
}
|
|
|
|
return &pb.FindNSRouteResponse{NsRoute: &pb.NSRoute{
|
|
Id: int64(route.Id),
|
|
IsOn: route.IsOn,
|
|
Name: route.Name,
|
|
RangesJSON: route.Ranges,
|
|
IsPublic: route.IsPublic,
|
|
Priority: types.Int32(route.Priority),
|
|
NsCluster: pbCluster,
|
|
NsDomain: pbDomain,
|
|
NsRouteCategory: pbCategory,
|
|
}}, nil
|
|
}
|
|
|
|
// CountAllNSRoutes 查询自定义线路数量
|
|
func (this *NSRouteService) CountAllNSRoutes(ctx context.Context, req *pb.CountAllNSRoutesRequest) (*pb.RPCCountResponse, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if userId > 0 {
|
|
req.UserId = userId
|
|
}
|
|
|
|
var tx = this.NullTx()
|
|
countRoutes, err := nameservers.SharedNSRouteDAO.CountAllEnabledRoutes(tx, req.NsClusterId, req.NsClusterId, req.UserId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.SuccessCount(countRoutes)
|
|
}
|
|
|
|
// FindAllNSRoutes 读取所有自定义线路
|
|
func (this *NSRouteService) FindAllNSRoutes(ctx context.Context, req *pb.FindAllNSRoutesRequest) (*pb.FindAllNSRoutesResponse, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var tx = this.NullTx()
|
|
|
|
if userId > 0 {
|
|
req.UserId = userId
|
|
}
|
|
|
|
routes, err := nameservers.SharedNSRouteDAO.FindAllEnabledRoutes(tx, req.NsClusterId, req.NsDomainId, req.UserId, req.NsRouteCategoryId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pbRoutes = []*pb.NSRoute{}
|
|
for _, route := range routes {
|
|
// 集群
|
|
var pbCluster *pb.NSCluster
|
|
if route.ClusterId > 0 {
|
|
cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(route.ClusterId))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if cluster != nil {
|
|
pbCluster = &pb.NSCluster{
|
|
Id: int64(cluster.Id),
|
|
IsOn: cluster.IsOn,
|
|
Name: cluster.Name,
|
|
}
|
|
}
|
|
}
|
|
|
|
// 域名
|
|
var pbDomain *pb.NSDomain
|
|
if route.DomainId > 0 {
|
|
domain, err := nameservers.SharedNSDomainDAO.FindEnabledNSDomain(tx, int64(route.DomainId))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if domain != nil {
|
|
pbDomain = &pb.NSDomain{
|
|
Id: int64(domain.Id),
|
|
Name: domain.Name,
|
|
IsOn: domain.IsOn,
|
|
}
|
|
}
|
|
}
|
|
|
|
// 分类
|
|
var pbCategory *pb.NSRouteCategory
|
|
if route.CategoryId > 0 {
|
|
category, err := nameservers.SharedNSRouteCategoryDAO.FindCategory(tx, int64(route.CategoryId))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if category != nil {
|
|
pbCategory = &pb.NSRouteCategory{
|
|
Id: int64(category.Id),
|
|
Name: category.Name,
|
|
IsOn: category.IsOn,
|
|
Order: types.Int32(category.Order),
|
|
}
|
|
}
|
|
}
|
|
|
|
pbRoutes = append(pbRoutes, &pb.NSRoute{
|
|
Id: int64(route.Id),
|
|
IsOn: route.IsOn,
|
|
Code: "id:" + types.String(route.Id),
|
|
Name: route.Name,
|
|
IsPublic: route.IsPublic,
|
|
RangesJSON: route.Ranges,
|
|
Order: types.Int32(route.Order),
|
|
Priority: types.Int32(route.Priority),
|
|
NsCluster: pbCluster,
|
|
NsDomain: pbDomain,
|
|
NsRouteCategory: pbCategory,
|
|
})
|
|
}
|
|
|
|
// 按照分类排序
|
|
if len(pbRoutes) > 0 {
|
|
sort.Slice(pbRoutes, func(i, j int) bool {
|
|
var route1 = pbRoutes[i]
|
|
var route2 = pbRoutes[j]
|
|
|
|
// route1.category = nil
|
|
if route1.NsRouteCategory == nil {
|
|
if route2.NsRouteCategory == nil {
|
|
if route1.Order == route2.Order {
|
|
return route1.Id < route2.Id
|
|
}
|
|
return route1.Order > route2.Order
|
|
}
|
|
return true
|
|
}
|
|
|
|
// route1.category != nil && route2.category = nil
|
|
if route2.NsRouteCategory == nil {
|
|
return false
|
|
}
|
|
|
|
// 同一个分类
|
|
if route1.NsRouteCategory.Id == route2.NsRouteCategory.Id {
|
|
if route1.Order == route2.Order {
|
|
return route1.Id < route2.Id
|
|
}
|
|
return route1.Order > route2.Order
|
|
}
|
|
|
|
if route1.NsRouteCategory.Order == route2.NsRouteCategory.Order {
|
|
return route1.NsRouteCategory.Id < route2.NsRouteCategory.Id
|
|
}
|
|
|
|
return route1.NsRouteCategory.Order > route2.NsRouteCategory.Order
|
|
})
|
|
}
|
|
|
|
return &pb.FindAllNSRoutesResponse{NsRoutes: pbRoutes}, nil
|
|
}
|
|
|
|
// FindAllPublicNSRoutes 读取所有公用的自定义线路
|
|
// 目前只允许读取系统管理员设置的公用自定义线路
|
|
func (this *NSRouteService) FindAllPublicNSRoutes(ctx context.Context, req *pb.FindAllPublicRoutesRequest) (*pb.FindAllPublicRoutesResponse, error) {
|
|
_, err := this.ValidateUserNode(ctx, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var tx = this.NullTx()
|
|
routes, err := nameservers.SharedNSRouteDAO.FindAllPublicRoutes(tx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pbRoutes = []*pb.NSRoute{}
|
|
for _, route := range routes {
|
|
// 分类
|
|
var pbCategory *pb.NSRouteCategory
|
|
if route.CategoryId > 0 {
|
|
category, err := nameservers.SharedNSRouteCategoryDAO.FindCategory(tx, int64(route.CategoryId))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if category != nil {
|
|
// 如果分类未启用,则当前分类下面的线路也不显示
|
|
if !category.IsOn {
|
|
continue
|
|
}
|
|
|
|
pbCategory = &pb.NSRouteCategory{
|
|
Id: int64(category.Id),
|
|
Name: category.Name,
|
|
IsOn: category.IsOn,
|
|
Order: types.Int32(category.Order),
|
|
}
|
|
}
|
|
}
|
|
|
|
pbRoutes = append(pbRoutes, &pb.NSRoute{
|
|
Id: int64(route.Id),
|
|
IsOn: route.IsOn,
|
|
Code: "id:" + types.String(route.Id),
|
|
Name: route.Name,
|
|
IsPublic: route.IsPublic,
|
|
RangesJSON: route.Ranges,
|
|
Order: types.Int32(route.Order),
|
|
Priority: types.Int32(route.Priority),
|
|
NsCluster: nil,
|
|
NsDomain: nil,
|
|
NsRouteCategory: pbCategory,
|
|
})
|
|
}
|
|
|
|
// 按照分类排序
|
|
if len(pbRoutes) > 0 {
|
|
sort.Slice(pbRoutes, func(i, j int) bool {
|
|
var route1 = pbRoutes[i]
|
|
var route2 = pbRoutes[j]
|
|
|
|
// route1.category = nil
|
|
if route1.NsRouteCategory == nil {
|
|
if route2.NsRouteCategory == nil {
|
|
if route1.Order == route2.Order {
|
|
return route1.Id < route2.Id
|
|
}
|
|
return route1.Order > route2.Order
|
|
}
|
|
return true
|
|
}
|
|
|
|
// route1.category != nil && route2.category = nil
|
|
if route2.NsRouteCategory == nil {
|
|
return false
|
|
}
|
|
|
|
// 同一个分类
|
|
if route1.NsRouteCategory.Id == route2.NsRouteCategory.Id {
|
|
if route1.Order == route2.Order {
|
|
return route1.Id < route2.Id
|
|
}
|
|
return route1.Order > route2.Order
|
|
}
|
|
|
|
if route1.NsRouteCategory.Order == route2.NsRouteCategory.Order {
|
|
return route1.NsRouteCategory.Id < route2.NsRouteCategory.Id
|
|
}
|
|
|
|
return route1.NsRouteCategory.Order > route2.NsRouteCategory.Order
|
|
})
|
|
}
|
|
|
|
return &pb.FindAllPublicRoutesResponse{NsRoutes: pbRoutes}, nil
|
|
}
|
|
|
|
// UpdateNSRouteOrders 设置自定义线路排序
|
|
func (this *NSRouteService) UpdateNSRouteOrders(ctx context.Context, req *pb.UpdateNSRouteOrdersRequest) (*pb.RPCSuccess, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var tx = this.NullTx()
|
|
|
|
// 检查权限
|
|
if userId > 0 {
|
|
for _, routeId := range req.NsRouteIds {
|
|
err = nameservers.SharedNSRouteDAO.CheckUserRoute(tx, userId, routeId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
|
|
err = nameservers.SharedNSRouteDAO.UpdateRouteOrders(tx, req.NsRouteIds)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
// ListNSRoutesAfterVersion 根据版本列出一组自定义线路
|
|
func (this *NSRouteService) ListNSRoutesAfterVersion(ctx context.Context, req *pb.ListNSRoutesAfterVersionRequest) (*pb.ListNSRoutesAfterVersionResponse, error) {
|
|
_, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeDNS)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 集群ID
|
|
var tx = this.NullTx()
|
|
routes, err := nameservers.SharedNSRouteDAO.ListRoutesAfterVersion(tx, req.Version, 2000)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var pbRoutes []*pb.NSRoute
|
|
for _, route := range routes {
|
|
// 集群
|
|
var pbCluster *pb.NSCluster
|
|
if route.ClusterId > 0 {
|
|
pbCluster = &pb.NSCluster{Id: int64(route.ClusterId)}
|
|
}
|
|
|
|
// 域名
|
|
var pbDomain *pb.NSDomain
|
|
if route.DomainId > 0 {
|
|
pbDomain = &pb.NSDomain{Id: int64(route.DomainId)}
|
|
}
|
|
|
|
pbRoutes = append(pbRoutes, &pb.NSRoute{
|
|
Id: int64(route.Id),
|
|
IsOn: route.IsOn,
|
|
Name: "",
|
|
RangesJSON: route.Ranges,
|
|
IsDeleted: route.State == nameservers.NSRouteStateDisabled,
|
|
Order: types.Int32(route.Order),
|
|
Priority: types.Int32(route.Priority),
|
|
Version: int64(route.Version),
|
|
UserId: types.Int64(route.UserId),
|
|
NsCluster: pbCluster,
|
|
NsDomain: pbDomain,
|
|
})
|
|
}
|
|
return &pb.ListNSRoutesAfterVersionResponse{NsRoutes: pbRoutes}, nil
|
|
}
|
|
|
|
// FindAllDefaultWorldRegionRoutes 查找默认的世界区域线路
|
|
func (this *NSRouteService) FindAllDefaultWorldRegionRoutes(ctx context.Context, req *pb.FindAllDefaultWorldRegionRoutesRequest) (*pb.FindAllDefaultWorldRegionRoutesResponse, error) {
|
|
_, _, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var pbRoutes = []*pb.NSRoute{}
|
|
for _, route := range dnsconfigs.AllDefaultWorldRegionRoutes {
|
|
pbRoutes = append(pbRoutes, &pb.NSRoute{
|
|
Code: route.Code,
|
|
Name: route.Name,
|
|
})
|
|
}
|
|
return &pb.FindAllDefaultWorldRegionRoutesResponse{
|
|
NsRoutes: pbRoutes,
|
|
}, nil
|
|
}
|
|
|
|
// FindAllDefaultChinaProvinceRoutes 查找默认的中国省份线路
|
|
func (this *NSRouteService) FindAllDefaultChinaProvinceRoutes(ctx context.Context, req *pb.FindAllDefaultChinaProvinceRoutesRequest) (*pb.FindAllDefaultChinaProvinceRoutesResponse, error) {
|
|
_, _, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var pbRoutes = []*pb.NSRoute{}
|
|
for _, route := range dnsconfigs.AllDefaultChinaProvinceRoutes {
|
|
pbRoutes = append(pbRoutes, &pb.NSRoute{
|
|
Code: route.Code,
|
|
Name: route.Name,
|
|
})
|
|
}
|
|
return &pb.FindAllDefaultChinaProvinceRoutesResponse{
|
|
NsRoutes: pbRoutes,
|
|
}, nil
|
|
}
|
|
|
|
// FindAllDefaultISPRoutes 查找默认的ISP线路
|
|
func (this *NSRouteService) FindAllDefaultISPRoutes(ctx context.Context, req *pb.FindAllDefaultISPRoutesRequest) (*pb.FindAllDefaultISPRoutesResponse, error) {
|
|
_, _, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var pbRoutes = []*pb.NSRoute{}
|
|
for _, route := range dnsconfigs.AllDefaultISPRoutes {
|
|
pbRoutes = append(pbRoutes, &pb.NSRoute{
|
|
Code: route.Code,
|
|
Name: route.Name,
|
|
})
|
|
}
|
|
return &pb.FindAllDefaultISPRoutesResponse{
|
|
NsRoutes: pbRoutes,
|
|
}, nil
|
|
}
|
|
|
|
// FindAllAgentNSRoutes 查找默认的搜索引擎线路
|
|
func (this *NSRouteService) FindAllAgentNSRoutes(ctx context.Context, req *pb.FindAllAgentNSRoutesRequest) (*pb.FindAllAgentNSRoutesResponse, error) {
|
|
_, _, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var tx = this.NullTx()
|
|
agents, err := clients.SharedClientAgentDAO.FindAllNSAgents(tx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var pbRoutes = []*pb.NSRoute{}
|
|
for _, agent := range agents {
|
|
pbRoutes = append(pbRoutes, &pb.NSRoute{
|
|
Code: agent.NSRouteCode(),
|
|
Name: agent.Name,
|
|
})
|
|
}
|
|
|
|
pbRoutes = append(pbRoutes, &pb.NSRoute{
|
|
Code: "agent",
|
|
Name: "搜索引擎",
|
|
})
|
|
|
|
return &pb.FindAllAgentNSRoutesResponse{NsRoutes: pbRoutes}, nil
|
|
}
|