217 lines
7.2 KiB
Go
217 lines
7.2 KiB
Go
package httpdns
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
"github.com/iwind/TeaGo/dbs"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/metadata"
|
|
)
|
|
|
|
// HTTPDNSClusterService HTTPDNS集群服务
|
|
type HTTPDNSClusterService struct {
|
|
services.BaseService
|
|
pb.UnimplementedHTTPDNSClusterServiceServer
|
|
}
|
|
|
|
func (this *HTTPDNSClusterService) CreateHTTPDNSCluster(ctx context.Context, req *pb.CreateHTTPDNSClusterRequest) (*pb.CreateHTTPDNSClusterResponse, error) {
|
|
_, err := this.ValidateAdmin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(req.Name) == 0 {
|
|
return nil, errors.New("required 'name'")
|
|
}
|
|
var clusterId int64
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
clusterId, err = models.SharedHTTPDNSClusterDAO.CreateCluster(tx, req.Name, req.ServiceDomain, req.DefaultTTL, req.FallbackTimeoutMs, req.InstallDir, req.TlsPolicyJSON, req.IsOn, req.IsDefault, req.AutoRemoteStart, req.AccessLogIsOn, req.TimeZone)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return notifyHTTPDNSClusterTask(tx, clusterId, models.HTTPDNSNodeTaskTypeConfigChanged)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &pb.CreateHTTPDNSClusterResponse{ClusterId: clusterId}, nil
|
|
}
|
|
|
|
func (this *HTTPDNSClusterService) UpdateHTTPDNSCluster(ctx context.Context, req *pb.UpdateHTTPDNSClusterRequest) (*pb.RPCSuccess, error) {
|
|
_, err := this.ValidateAdmin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Compatibility fallback:
|
|
// If protobuf schemas between edge-admin and edge-api are inconsistent,
|
|
// these newly-added fields may be lost on the wire. Read gRPC metadata as fallback.
|
|
if md, ok := metadata.FromIncomingContext(ctx); ok {
|
|
if values := md.Get("x-httpdns-auto-remote-start"); len(values) > 0 {
|
|
raw := strings.ToLower(strings.TrimSpace(values[0]))
|
|
req.AutoRemoteStart = raw == "1" || raw == "true" || raw == "on" || raw == "yes" || raw == "enabled"
|
|
}
|
|
if values := md.Get("x-httpdns-access-log-is-on"); len(values) > 0 {
|
|
raw := strings.ToLower(strings.TrimSpace(values[0]))
|
|
req.AccessLogIsOn = raw == "1" || raw == "true" || raw == "on" || raw == "yes" || raw == "enabled"
|
|
}
|
|
if values := md.Get("x-httpdns-time-zone"); len(values) > 0 {
|
|
raw := strings.TrimSpace(values[0])
|
|
if len(raw) > 0 {
|
|
req.TimeZone = raw
|
|
}
|
|
}
|
|
}
|
|
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
// 先读取旧的 TLS 配置,用于判断是否真正发生了变化
|
|
var oldTLSJSON string
|
|
oldCluster, findErr := models.SharedHTTPDNSClusterDAO.FindEnabledCluster(tx, req.ClusterId)
|
|
if findErr == nil && oldCluster != nil {
|
|
oldTLSJSON = string(oldCluster.TLSPolicy)
|
|
}
|
|
|
|
err = models.SharedHTTPDNSClusterDAO.UpdateCluster(tx, req.ClusterId, req.Name, req.ServiceDomain, req.DefaultTTL, req.FallbackTimeoutMs, req.InstallDir, req.TlsPolicyJSON, req.IsOn, req.IsDefault, req.AutoRemoteStart, req.AccessLogIsOn, req.TimeZone)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
taskType := models.HTTPDNSNodeTaskTypeConfigChanged
|
|
if len(req.TlsPolicyJSON) > 0 && string(req.TlsPolicyJSON) != oldTLSJSON {
|
|
taskType = models.HTTPDNSNodeTaskTypeTLSChanged
|
|
}
|
|
return notifyHTTPDNSClusterTask(tx, req.ClusterId, taskType)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
func (this *HTTPDNSClusterService) DeleteHTTPDNSCluster(ctx context.Context, req *pb.DeleteHTTPDNSClusterRequest) (*pb.RPCSuccess, error) {
|
|
_, err := this.ValidateAdmin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
err = models.SharedHTTPDNSClusterDAO.DisableCluster(tx, req.ClusterId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return notifyHTTPDNSClusterTask(tx, req.ClusterId, models.HTTPDNSNodeTaskTypeConfigChanged)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
func (this *HTTPDNSClusterService) FindHTTPDNSCluster(ctx context.Context, req *pb.FindHTTPDNSClusterRequest) (*pb.FindHTTPDNSClusterResponse, error) {
|
|
_, err := this.ValidateAdmin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cluster, err := models.SharedHTTPDNSClusterDAO.FindEnabledCluster(this.NullTx(), req.ClusterId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if cluster != nil {
|
|
_ = grpc.SetHeader(ctx, metadata.Pairs(
|
|
"x-httpdns-auto-remote-start", fmt.Sprintf("%t", cluster.AutoRemoteStart),
|
|
"x-httpdns-access-log-is-on", fmt.Sprintf("%t", cluster.AccessLogIsOn),
|
|
"x-httpdns-time-zone", cluster.TimeZone,
|
|
))
|
|
}
|
|
return &pb.FindHTTPDNSClusterResponse{Cluster: toPBCluster(cluster)}, nil
|
|
}
|
|
|
|
func (this *HTTPDNSClusterService) ListHTTPDNSClusters(ctx context.Context, req *pb.ListHTTPDNSClustersRequest) (*pb.ListHTTPDNSClustersResponse, error) {
|
|
_, err := this.ValidateAdmin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
clusters, err := models.SharedHTTPDNSClusterDAO.ListEnabledClusters(this.NullTx(), req.Offset, req.Size, req.Keyword)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pbClusters []*pb.HTTPDNSCluster
|
|
for _, cluster := range clusters {
|
|
pbClusters = append(pbClusters, toPBCluster(cluster))
|
|
}
|
|
return &pb.ListHTTPDNSClustersResponse{Clusters: pbClusters}, nil
|
|
}
|
|
|
|
func (this *HTTPDNSClusterService) FindAllHTTPDNSClusters(ctx context.Context, req *pb.FindAllHTTPDNSClustersRequest) (*pb.FindAllHTTPDNSClustersResponse, error) {
|
|
_, _, validateErr := this.ValidateAdminAndUser(ctx, true)
|
|
isNode := false
|
|
if validateErr != nil {
|
|
if _, nodeErr := this.ValidateHTTPDNSNode(ctx); nodeErr != nil {
|
|
return nil, validateErr
|
|
}
|
|
isNode = true
|
|
}
|
|
clusters, err := models.SharedHTTPDNSClusterDAO.FindAllEnabledClusters(this.NullTx())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pbClusters []*pb.HTTPDNSCluster
|
|
for _, cluster := range clusters {
|
|
if isNode {
|
|
// 节点调用时解析证书引用,嵌入实际 PEM 数据
|
|
pbClusters = append(pbClusters, toPBClusterWithResolvedCerts(this.NullTx(), cluster))
|
|
} else {
|
|
pbClusters = append(pbClusters, toPBCluster(cluster))
|
|
}
|
|
}
|
|
return &pb.FindAllHTTPDNSClustersResponse{Clusters: pbClusters}, nil
|
|
}
|
|
|
|
func (this *HTTPDNSClusterService) UpdateHTTPDNSClusterDefault(ctx context.Context, req *pb.UpdateHTTPDNSClusterDefaultRequest) (*pb.RPCSuccess, error) {
|
|
_, err := this.ValidateAdmin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
err = models.SharedHTTPDNSClusterDAO.UpdateDefaultCluster(tx, req.ClusterId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
clusters, err := models.SharedHTTPDNSClusterDAO.FindAllEnabledClusters(tx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, cluster := range clusters {
|
|
err = notifyHTTPDNSClusterTask(tx, int64(cluster.Id), models.HTTPDNSNodeTaskTypeConfigChanged)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
func (this *HTTPDNSClusterService) ListHTTPDNSNodesWithClusterId(ctx context.Context, req *pb.ListHTTPDNSNodesWithClusterIdRequest) (*pb.ListHTTPDNSNodesWithClusterIdResponse, error) {
|
|
_, _, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nodes, err := models.SharedHTTPDNSNodeDAO.ListEnabledNodes(this.NullTx(), req.ClusterId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pbNodes []*pb.HTTPDNSNode
|
|
for _, node := range nodes {
|
|
pbNodes = append(pbNodes, toPBNode(node))
|
|
}
|
|
return &pb.ListHTTPDNSNodesWithClusterIdResponse{Nodes: pbNodes}, nil
|
|
}
|