diff --git a/internal/web/actions/default/clusters/cluster/settings/dns/index.go b/internal/web/actions/default/clusters/cluster/settings/dns/index.go index 50bc0bd0..43564fa5 100644 --- a/internal/web/actions/default/clusters/cluster/settings/dns/index.go +++ b/internal/web/actions/default/clusters/cluster/settings/dns/index.go @@ -14,7 +14,7 @@ type IndexAction struct { } func (this *IndexAction) Init() { - this.Nav("", "setting", "") + this.Nav("", "setting", "index") this.SecondMenu("dns") } diff --git a/internal/web/actions/default/clusters/cluster/settings/dns/records.go b/internal/web/actions/default/clusters/cluster/settings/dns/records.go new file mode 100644 index 00000000..1add9963 --- /dev/null +++ b/internal/web/actions/default/clusters/cluster/settings/dns/records.go @@ -0,0 +1,303 @@ +// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package dns + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/utils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" + timeutil "github.com/iwind/TeaGo/utils/time" +) + +type RecordsAction struct { + actionutils.ParentAction +} + +func (this *RecordsAction) Init() { + this.Nav("", "setting", "records") + this.SecondMenu("dns") +} + +func (this *RecordsAction) RunGet(params struct { + ClusterId int64 +}) { + // 集群信息 + clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: params.ClusterId}) + if err != nil { + this.ErrorPage(err) + return + } + var cluster = clusterResp.NodeCluster + if cluster == nil { + this.NotFound("nodeCluster", params.ClusterId) + return + } + this.Data["cluster"] = maps.Map{ + "id": cluster.Id, + "name": cluster.Name, + } + + // DNS信息 + dnsResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeClusterDNS(this.AdminContext(), &pb.FindEnabledNodeClusterDNSRequest{NodeClusterId: params.ClusterId}) + if err != nil { + this.ErrorPage(err) + return + } + var defaultRoute = dnsResp.DefaultRoute + var domainName = "" + var dnsMap = maps.Map{ + "dnsName": dnsResp.Name, + "domainId": 0, + "domainName": "", + "providerId": 0, + "providerName": "", + "providerTypeName": "", + } + if dnsResp.Domain != nil { + domainName = dnsResp.Domain.Name + dnsMap["domainId"] = dnsResp.Domain.Id + dnsMap["domainName"] = dnsResp.Domain.Name + } + if dnsResp.Provider != nil { + dnsMap["providerId"] = dnsResp.Provider.Id + dnsMap["providerName"] = dnsResp.Provider.Name + dnsMap["providerTypeName"] = dnsResp.Provider.TypeName + } + + if len(dnsResp.CnameRecords) > 0 { + dnsMap["cnameRecords"] = dnsResp.CnameRecords + } else { + dnsMap["cnameRecords"] = []string{} + } + + this.Data["dnsInfo"] = dnsMap + + // 未安装的节点 + notInstalledNodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodesDNSWithNodeClusterIdRequest{ + NodeClusterId: params.ClusterId, + IsInstalled: false, + }) + if err != nil { + this.ErrorPage(err) + return + } + var allNodes = notInstalledNodesResp.Nodes + + // 节点DNS解析记录 + nodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodesDNSWithNodeClusterIdRequest{ + NodeClusterId: params.ClusterId, + IsInstalled: true, + }) + if err != nil { + this.ErrorPage(err) + return + } + var installedNodeIdsMap = map[int64]bool{} + for _, node := range nodesResp.Nodes { + installedNodeIdsMap[node.Id] = true + } + + allNodes = append(allNodes, nodesResp.Nodes...) + + var nodeMaps = []maps.Map{} + for _, node := range allNodes { + var isInstalled = installedNodeIdsMap[node.Id] + + if len(node.Routes) > 0 { + for _, route := range node.Routes { + // 检查是否已解析 + var isResolved = false + if isInstalled && cluster.DnsDomainId > 0 && len(cluster.DnsName) > 0 && len(node.IpAddr) > 0 { + var recordType = "A" + if utils.IsIPv6(node.IpAddr) { + recordType = "AAAA" + } + checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{ + DnsDomainId: cluster.DnsDomainId, + Name: cluster.DnsName, + Type: recordType, + Route: route.Code, + Value: node.IpAddr, + }) + if err != nil { + this.ErrorPage(err) + return + } + isResolved = checkResp.IsOk + } + + nodeMaps = append(nodeMaps, maps.Map{ + "id": node.Id, + "name": node.Name, + "ipAddr": node.IpAddr, + "ipAddrId": node.NodeIPAddressId, + "route": maps.Map{ + "name": route.Name, + "code": route.Code, + }, + "clusterId": node.NodeClusterId, + "isResolved": isResolved, + "isInstalled": isInstalled, + "isBackup": node.IsBackupForCluster || node.IsBackupForGroup, + "isOffline": node.IsOffline, + }) + } + } else { + // 默认线路 + var isResolved = false + if isInstalled && len(defaultRoute) > 0 { + var recordType = "A" + if utils.IsIPv6(node.IpAddr) { + recordType = "AAAA" + } + checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{ + DnsDomainId: cluster.DnsDomainId, + Name: cluster.DnsName, + Type: recordType, + Route: defaultRoute, + Value: node.IpAddr, + }) + if err != nil { + this.ErrorPage(err) + return + } + isResolved = checkResp.IsOk + } + nodeMaps = append(nodeMaps, maps.Map{ + "id": node.Id, + "name": node.Name, + "ipAddr": node.IpAddr, + "ipAddrId": node.NodeIPAddressId, + "route": maps.Map{ + "name": "", + "code": "", + }, + "clusterId": node.NodeClusterId, + "isResolved": isResolved, + "isInstalled": isInstalled, + "isBackup": node.IsBackupForCluster || node.IsBackupForGroup, + "isOffline": node.IsOffline, + }) + } + } + this.Data["nodes"] = nodeMaps + + // 代理服务解析记录 + serversResp, err := this.RPC().ServerRPC().FindAllEnabledServersDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledServersDNSWithNodeClusterIdRequest{NodeClusterId: params.ClusterId}) + if err != nil { + this.ErrorPage(err) + return + } + var serverMaps = []maps.Map{} + for _, server := range serversResp.Servers { + // 检查是否已解析 + isResolved := false + if cluster.DnsDomainId > 0 && len(cluster.DnsName) > 0 && len(server.DnsName) > 0 && len(domainName) > 0 { + checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{ + DnsDomainId: cluster.DnsDomainId, + Name: server.DnsName, + Type: "CNAME", + Value: cluster.DnsName + "." + domainName, + }) + if err != nil { + this.ErrorPage(err) + return + } + isResolved = checkResp.IsOk + } + + serverMaps = append(serverMaps, maps.Map{ + "id": server.Id, + "name": server.Name, + "dnsName": server.DnsName, + "isResolved": isResolved, + }) + } + this.Data["servers"] = serverMaps + + // 检查解析记录是否有变化 + checkChangesResp, err := this.RPC().NodeClusterRPC().CheckNodeClusterDNSChanges(this.AdminContext(), &pb.CheckNodeClusterDNSChangesRequest{NodeClusterId: params.ClusterId}) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["dnsHasChanges"] = checkChangesResp.IsChanged + + // 需要解决的问题 + issuesResp, err := this.RPC().DNSRPC().FindAllDNSIssues(this.AdminContext(), &pb.FindAllDNSIssuesRequest{ + NodeClusterId: params.ClusterId, + }) + if err != nil { + this.ErrorPage(err) + return + } + var issueMaps = []maps.Map{} + for _, issue := range issuesResp.Issues { + issueMaps = append(issueMaps, maps.Map{ + "target": issue.Target, + "targetId": issue.TargetId, + "type": issue.Type, + "description": issue.Description, + "params": issue.Params, + }) + } + this.Data["issues"] = issueMaps + + // 当前正在执行的任务 + resp, err := this.RPC().DNSTaskRPC().FindAllDoingDNSTasks(this.AdminContext(), &pb.FindAllDoingDNSTasksRequest{ + NodeClusterId: params.ClusterId, + }) + if err != nil { + this.ErrorPage(err) + return + } + var taskMaps = []maps.Map{} + for _, task := range resp.DnsTasks { + var clusterMap maps.Map = nil + var nodeMap maps.Map = nil + var serverMap maps.Map = nil + var domainMap maps.Map = nil + + if task.NodeCluster != nil { + clusterMap = maps.Map{ + "id": task.NodeCluster.Id, + "name": task.NodeCluster.Name, + } + } + if task.Node != nil { + nodeMap = maps.Map{ + "id": task.Node.Id, + "name": task.Node.Name, + } + } + if task.Server != nil { + serverMap = maps.Map{ + "id": task.Server.Id, + "name": task.Server.Name, + } + } + if task.DnsDomain != nil { + domainMap = maps.Map{ + "id": task.DnsDomain.Id, + "name": task.DnsDomain.Name, + } + } + + taskMaps = append(taskMaps, maps.Map{ + "id": task.Id, + "type": task.Type, + "isDone": task.IsDone, + "isOk": task.IsOk, + "error": task.Error, + "updatedTime": timeutil.FormatTime("Y-m-d H:i:s", task.UpdatedAt), + "cluster": clusterMap, + "node": nodeMap, + "server": serverMap, + "domain": domainMap, + }) + } + this.Data["tasks"] = taskMaps + + this.Show() +} diff --git a/internal/web/actions/default/clusters/cluster/settings/init.go b/internal/web/actions/default/clusters/cluster/settings/init.go index 36d98a73..fa6ed537 100644 --- a/internal/web/actions/default/clusters/cluster/settings/init.go +++ b/internal/web/actions/default/clusters/cluster/settings/init.go @@ -40,6 +40,7 @@ func init() { // DNS Prefix("/clusters/cluster/settings/dns"). GetPost("", new(dns.IndexAction)). + Get("/records", new(dns.RecordsAction)). Post("/randomName", new(dns.RandomNameAction)). // 系统服务设置 diff --git a/web/views/@default/clusters/cluster/settings/dns/@menu.html b/web/views/@default/clusters/cluster/settings/dns/@menu.html new file mode 100644 index 00000000..d0c16223 --- /dev/null +++ b/web/views/@default/clusters/cluster/settings/dns/@menu.html @@ -0,0 +1,4 @@ + + DNS设置 + 解析记录 + diff --git a/web/views/@default/clusters/cluster/settings/dns/index.html b/web/views/@default/clusters/cluster/settings/dns/index.html index 78a8c387..923a3849 100644 --- a/web/views/@default/clusters/cluster/settings/dns/index.html +++ b/web/views/@default/clusters/cluster/settings/dns/index.html @@ -3,7 +3,8 @@ {$template "/left_menu_with_menu"}
-

查看DNS解析记录 »

+ {$template "menu"} +
diff --git a/web/views/@default/clusters/cluster/settings/dns/records.html b/web/views/@default/clusters/cluster/settings/dns/records.html new file mode 100644 index 00000000..f0fc5043 --- /dev/null +++ b/web/views/@default/clusters/cluster/settings/dns/records.html @@ -0,0 +1,203 @@ +{$layout} +{$template "../menu"} +{$template "/left_menu_with_menu"} + +
+ {$template "menu"} + + + + + + + + + + + + + + + + + + + +
DNS子域名 + {{dnsInfo.dnsName}}.{{dnsInfo.domainName}} + 没有设置 +
DNS服务商 +
+ {{dnsInfo.providerTypeName}} - {{dnsInfo.providerName}} +
+ 请先设置域名 + 没有设置 +
自动设置CNAME记录 + 暂时还没有设置。 +
+ {{record}} +
+
操作 +
+ 检测到解析记录有变化,需要同步 + DNS服务商同步 +
+ DNS服务商同步中... +
+ + +
+

正在执行的任务

+ + + + + + + + + + + + + + + + + +
对象任务状态触发时间
+ {{task.cluster.name}} + + + {{task.node.name}} + {{task.server.name}} + {{task.domain.name}} + + 集群 + 节点 + 网站 + 域名 + + {{task.error}} + 正在同步... + {{task.updatedTime}} + +
+
+ + +
+

需要修复的问题

+ + + + + + + + + + + + + +
问题对象问题描述操作
+
+ 集群 "{{issue.target}}" +
+
+ 集群 "{{issue.params.clusterName}}" 节点 "{{issue.target}}" +
+
+ {{issue.description}} + +
+ 修复 +
+
+ 修复 +
+
+
+
+ +

下面的DNS解析记录也可以手工在DNS服务商提供的管理平台添加。

+ + +

节点DNS解析记录   ({{nodes.length}}个)

+

暂时没有需要设置的DNS记录。

+ + + + + + + + + + + + + + + + + + + + + +
节点子域名记录类型记录值线路状态操作
{{node.name}} + {{dnsInfo.dnsName}} + 没有设置 + + AAAA + A + + {{node.ipAddr}} + 没有设置 + + {{node.route.name}} + 没有设置 + + 备用节点 + 已下线 +
+ + 已解析 + 未解析 + + 未安装 +
+
+ 修改 +
+ + +

网站解析记录   ({{servers.length}}个)

+

暂时没有需要设置的DNS记录。

+ + + + + + + + + + + + + + + + + +
网站子域名记录类型记录值状态
{{server.name}} {{server.dnsName}}CNAME + {{dnsInfo.dnsName}}.{{dnsInfo.domainName}}. + 没有设置 + + 已解析 + 未解析 +
+
\ No newline at end of file diff --git a/web/views/@default/clusters/cluster/settings/dns/records.js b/web/views/@default/clusters/cluster/settings/dns/records.js new file mode 100644 index 00000000..f56619b2 --- /dev/null +++ b/web/views/@default/clusters/cluster/settings/dns/records.js @@ -0,0 +1,56 @@ +Tea.context(function () { + this.updateCluster = function (clusterId) { + teaweb.popup("/dns/updateClusterPopup?clusterId=" + clusterId, { + height: "25em", + callback: function () { + teaweb.success("保存成功", function () { + teaweb.reload() + }) + } + }) + } + + this.updateNode = function (clusterId, nodeId, ipAddrId) { + teaweb.popup("/dns/issues/updateNodePopup?clusterId=" + clusterId + "&nodeId=" + nodeId + "&ipAddrId=" + (ipAddrId ? ipAddrId : 0), { + width: "46em", + height: "26em", + callback: function () { + teaweb.success("保存成功", function () { + teaweb.reload() + }) + } + }) + } + + this.isSyncing = false + this.syncCluster = function (clusterId) { + let that = this + teaweb.confirm("确定要执行数据同步吗?", function () { + that.isSyncing = true + that.$post("/dns/clusters/sync") + .params({clusterId: clusterId}) + .done(function () { + that.isSyncing = false + that.dnsHasChanges = false + }) + .success(function () { + teaweb.success("同步成功", function () { + teaweb.reload() + }) + }) + }) + } + + this.deleteTask = function (taskId) { + let that = this + teaweb.confirm("确定要删除这个任务吗?", function () { + that.$post("/dns/tasks/delete") + .params({ + taskId: taskId + }) + .success(function () { + teaweb.reload() + }) + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/dns/clusters/cluster.html b/web/views/@default/dns/clusters/cluster.html index 7bba52e5..8ce16946 100644 --- a/web/views/@default/dns/clusters/cluster.html +++ b/web/views/@default/dns/clusters/cluster.html @@ -13,7 +13,7 @@ {{cluster.name}} - 子域名 + DNS子域名 {{dnsInfo.dnsName}}.{{dnsInfo.domainName}} 没有设置