diff --git a/internal/db/models/db_node_dao.go b/internal/db/models/db_node_dao.go index a8093e35..a2ed7eda 100644 --- a/internal/db/models/db_node_dao.go +++ b/internal/db/models/db_node_dao.go @@ -1,9 +1,11 @@ package models import ( + "github.com/TeaOSLab/EdgeAPI/internal/errors" _ "github.com/go-sql-driver/mysql" "github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/dbs" + "github.com/iwind/TeaGo/types" ) const ( @@ -27,7 +29,7 @@ func NewDBNodeDAO() *DBNodeDAO { var SharedDBNodeDAO = NewDBNodeDAO() // 启用条目 -func (this *DBNodeDAO) EnableDBNode(id uint32) error { +func (this *DBNodeDAO) EnableDBNode(id int64) error { _, err := this.Query(). Pk(id). Set("state", DBNodeStateEnabled). @@ -36,7 +38,7 @@ func (this *DBNodeDAO) EnableDBNode(id uint32) error { } // 禁用条目 -func (this *DBNodeDAO) DisableDBNode(id uint32) error { +func (this *DBNodeDAO) DisableDBNode(id int64) error { _, err := this.Query(). Pk(id). Set("state", DBNodeStateDisabled). @@ -45,7 +47,7 @@ func (this *DBNodeDAO) DisableDBNode(id uint32) error { } // 查找启用中的条目 -func (this *DBNodeDAO) FindEnabledDBNode(id uint32) (*DBNode, error) { +func (this *DBNodeDAO) FindEnabledDBNode(id int64) (*DBNode, error) { result, err := this.Query(). Pk(id). Attr("state", DBNodeStateEnabled). @@ -57,9 +59,68 @@ func (this *DBNodeDAO) FindEnabledDBNode(id uint32) (*DBNode, error) { } // 根据主键查找名称 -func (this *DBNodeDAO) FindDBNodeName(id uint32) (string, error) { +func (this *DBNodeDAO) FindDBNodeName(id int64) (string, error) { return this.Query(). Pk(id). Result("name"). FindStringCol("") } + +// 计算可用的节点数量 +func (this *DBNodeDAO) CountAllEnabledNodes() (int64, error) { + return this.Query(). + State(DBNodeStateEnabled). + Count() +} + +// 获取单页的节点 +func (this *DBNodeDAO) ListEnabledNodes(offset int64, size int64) (result []*DBNode, err error) { + _, err = this.Query(). + State(DBNodeStateEnabled). + Offset(offset). + Limit(size). + Slice(&result). + DescPk(). + FindAll() + return +} + +// 创建节点 +func (this *DBNodeDAO) CreateDBNode(isOn bool, name string, description string, host string, port int32, database string, username string, password string, charset string) (int64, error) { + op := NewDBNodeOperator() + op.State = NodeStateEnabled + op.IsOn = isOn + op.Name = name + op.Description = description + op.Host = host + op.Port = port + op.Database = database + op.Username = username + op.Password = password + op.Charset = charset + _, err := this.Save(op) + if err != nil { + return 0, err + } + return types.Int64(op.Id), nil +} + +// 修改节点 +func (this *DBNodeDAO) UpdateNode(nodeId int64, isOn bool, name string, description string, host string, port int32, database string, username string, password string, charset string) error { + if nodeId <= 0 { + return errors.New("invalid nodeId") + } + op := NewDBNodeOperator() + op.Id = nodeId + op.IsOn = isOn + op.Name = name + op.Description = description + op.Host = host + op.Port = port + op.Database = database + op.Username = username + op.Password = password + op.Charset = charset + _, err := this.Save(op) + return err +} diff --git a/internal/db/models/db_node_model.go b/internal/db/models/db_node_model.go index 04fcca54..be90cc20 100644 --- a/internal/db/models/db_node_model.go +++ b/internal/db/models/db_node_model.go @@ -9,6 +9,7 @@ type DBNode struct { Description string `field:"description"` // 描述 Host string `field:"host"` // 主机 Port uint32 `field:"port"` // 端口 + Database string `field:"database"` // 数据库名称 Username string `field:"username"` // 用户名 Password string `field:"password"` // 密码 Charset string `field:"charset"` // 通讯字符集 @@ -28,6 +29,7 @@ type DBNodeOperator struct { Description interface{} // 描述 Host interface{} // 主机 Port interface{} // 端口 + Database interface{} // 数据库名称 Username interface{} // 用户名 Password interface{} // 密码 Charset interface{} // 通讯字符集 diff --git a/internal/nodes/api_node.go b/internal/nodes/api_node.go index c4791fb1..5531efde 100644 --- a/internal/nodes/api_node.go +++ b/internal/nodes/api_node.go @@ -163,6 +163,7 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err pb.RegisterSysSettingServiceServer(rpcServer, &services.SysSettingService{}) pb.RegisterHTTPFirewallRuleGroupServiceServer(rpcServer, &services.HTTPFirewallRuleGroupService{}) pb.RegisterHTTPFirewallRuleSetServiceServer(rpcServer, &services.HTTPFirewallRuleSetService{}) + pb.RegisterDBNodeServiceServer(rpcServer, &services.DBNodeService{}) err := rpcServer.Serve(listener) if err != nil { return errors.New("[API]start rpc failed: " + err.Error()) diff --git a/internal/rpc/services/service_db_node.go b/internal/rpc/services/service_db_node.go new file mode 100644 index 00000000..82c089ef --- /dev/null +++ b/internal/rpc/services/service_db_node.go @@ -0,0 +1,129 @@ +package services + +import ( + "context" + "github.com/TeaOSLab/EdgeAPI/internal/db/models" + rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/types" +) + +// 数据库节点相关服务 +type DBNodeService struct { +} + +// 创建数据库节点 +func (this *DBNodeService) CreateDBNode(ctx context.Context, req *pb.CreateDBNodeRequest) (*pb.CreateDBNodeResponse, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + nodeId, err := models.SharedDBNodeDAO.CreateDBNode(req.IsOn, req.Name, req.Description, req.Host, req.Port, req.Database, req.Username, req.Password, req.Charset) + if err != nil { + return nil, err + } + return &pb.CreateDBNodeResponse{NodeId: nodeId}, nil +} + +// 修改数据库节点 +func (this *DBNodeService) UpdateDBNode(ctx context.Context, req *pb.UpdateDBNodeRequest) (*pb.RPCUpdateSuccess, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + err = models.SharedDBNodeDAO.UpdateNode(req.NodeId, req.IsOn, req.Name, req.Description, req.Host, req.Port, req.Database, req.Username, req.Password, req.Charset) + if err != nil { + return nil, err + } + return rpcutils.RPCUpdateSuccess() +} + +// 删除节点 +func (this *DBNodeService) DeleteDBNode(ctx context.Context, req *pb.DeleteDBNodeRequest) (*pb.RPCDeleteSuccess, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + err = models.SharedDBNodeDAO.DisableDBNode(req.NodeId) + if err != nil { + return nil, err + } + return rpcutils.RPCDeleteSuccess() +} + +// 计算可用的数据库节点数量 +func (this *DBNodeService) CountAllEnabledDBNodes(ctx context.Context, req *pb.CountAllEnabledDBNodesRequest) (*pb.CountAllEnabledDBNodesResponse, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + count, err := models.SharedDBNodeDAO.CountAllEnabledNodes() + if err != nil { + return nil, err + } + return &pb.CountAllEnabledDBNodesResponse{Count: count}, nil +} + +// 列出单页的数据库节点 +func (this *DBNodeService) ListEnabledDBNodes(ctx context.Context, req *pb.ListEnabledDBNodesRequest) (*pb.ListEnabledDBNodesResponse, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + nodes, err := models.SharedDBNodeDAO.ListEnabledNodes(req.Offset, req.Size) + if err != nil { + return nil, err + } + + result := []*pb.DBNode{} + for _, node := range nodes { + result = append(result, &pb.DBNode{ + Id: int64(node.Id), + Name: node.Name, + Description: node.Description, + IsOn: node.IsOn == 1, + Host: node.Host, + Port: types.Int32(node.Port), + Database: node.Database, + Username: node.Username, + Password: node.Password, + Charset: node.Charset, + }) + } + return &pb.ListEnabledDBNodesResponse{Nodes: result}, nil +} + +// 根据ID查找可用的数据库节点 +func (this *DBNodeService) FindEnabledDBNode(ctx context.Context, req *pb.FindEnabledDBNodeRequest) (*pb.FindEnabledDBNodeResponse, error) { + // 校验请求 + _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin) + if err != nil { + return nil, err + } + + node, err := models.SharedDBNodeDAO.FindEnabledDBNode(req.NodeId) + if err != nil { + return nil, err + } + if node == nil { + return &pb.FindEnabledDBNodeResponse{Node: nil}, nil + } + return &pb.FindEnabledDBNodeResponse{Node: &pb.DBNode{ + Id: int64(node.Id), + Name: node.Name, + Description: node.Description, + IsOn: node.IsOn == 1, + Host: node.Host, + Port: types.Int32(node.Port), + Database: node.Database, + Username: node.Username, + Password: node.Password, + Charset: node.Charset, + }}, nil +}