diff --git a/go.mod b/go.mod index b521ac09..70cc6b08 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,5 @@ require ( golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect google.golang.org/grpc v1.38.0 - google.golang.org/protobuf v1.26.0 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 ) diff --git a/go.sum b/go.sum index c8d5c10c..de755d1b 100644 --- a/go.sum +++ b/go.sum @@ -141,6 +141,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -164,6 +165,7 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index eda79b11..50c9144b 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -404,6 +404,10 @@ func (this *RPCClient) NSRPC() pb.NSServiceClient { return pb.NewNSServiceClient(this.pickConn()) } +func (this *RPCClient) NSQuestionOptionRPC() pb.NSQuestionOptionServiceClient { + return pb.NewNSQuestionOptionServiceClient(this.pickConn()) +} + func (this *RPCClient) MetricItemRPC() pb.MetricItemServiceClient { return pb.NewMetricItemServiceClient(this.pickConn()) } diff --git a/internal/web/actions/default/ns/test/index.go b/internal/web/actions/default/ns/test/index.go new file mode 100644 index 00000000..18ad2299 --- /dev/null +++ b/internal/web/actions/default/ns/test/index.go @@ -0,0 +1,156 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package test + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils" + "github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "github.com/miekg/dns" + "net" + "regexp" +) + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "", "") +} + +func (this *IndexAction) RunGet(params struct{}) { + // 集群列表 + clustersResp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{}) + if err != nil { + this.ErrorPage(err) + return + } + var clusterMaps = []maps.Map{} + for _, cluster := range clustersResp.NsClusters { + if !cluster.IsOn { + continue + } + + countNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{ + NsClusterId: cluster.Id, + InstallState: 0, + ActiveState: 0, + Keyword: "", + }) + if err != nil { + this.ErrorPage(err) + return + } + var countNodes = countNodesResp.Count + if countNodes <= 0 { + continue + } + + clusterMaps = append(clusterMaps, maps.Map{ + "id": cluster.Id, + "name": cluster.Name, + "countNodes": countNodes, + }) + } + this.Data["clusters"] = clusterMaps + + // 记录类型 + this.Data["recordTypes"] = dnsconfigs.FindAllRecordTypeDefinitions() + + this.Show() +} + +func (this *IndexAction) RunPost(params struct { + NodeId int64 + Domain string + Type string + Ip string + ClientIP string + + Must *actions.Must +}) { + nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId}) + if err != nil { + this.ErrorPage(err) + return + } + var node = nodeResp.NsNode + if node == nil { + this.Fail("找不到要测试的节点") + } + + var isOk = false + var errMsg string + var isNetError = false + var result string + + defer func() { + this.Data["isOk"] = isOk + this.Data["err"] = errMsg + this.Data["isNetErr"] = isNetError + this.Data["result"] = result + this.Success() + }() + + if !domainutils.ValidateDomainFormat(params.Domain) { + errMsg = "域名格式错误" + return + } + + recordType, ok := dns.StringToType[params.Type] + if !ok { + errMsg = "不支持此记录类型" + return + } + + if len(params.ClientIP) > 0 && net.ParseIP(params.ClientIP) == nil { + errMsg = "客户端IP格式不正确" + return + } + + var optionId int64 + if len(params.ClientIP) > 0 { + optionResp, err := this.RPC().NSQuestionOptionRPC().CreateNSQuestionOption(this.AdminContext(), &pb.CreateNSQuestionOptionRequest{ + Name: "setRemoteAddr", + ValuesJSON: maps.Map{"ip": params.ClientIP}.AsJSON(), + }) + if err != nil { + this.ErrorPage(err) + return + } + optionId = optionResp.NsQuestionOptionId + defer func() { + _, err = this.RPC().NSQuestionOptionRPC().DeleteNSQuestionOption(this.AdminContext(), &pb.DeleteNSQuestionOptionRequest{NsQuestionOptionId: optionId}) + if err != nil { + this.ErrorPage(err) + } + }() + } + + c := new(dns.Client) + m := new(dns.Msg) + var domain = params.Domain + "." + if optionId > 0 { + domain = "$" + types.String(optionId) + "-" + domain + } + m.SetQuestion(domain, recordType) + r, _, err := c.Exchange(m, params.Ip+":53") + if err != nil { + errMsg = "解析过程中出错:" + err.Error() + + // 是否为网络错误 + if regexp.MustCompile(`timeout|connect`).MatchString(err.Error()) { + isNetError = true + } + + return + } + result = r.String() + result = regexp.MustCompile(`\$\d+-`).ReplaceAllString(result, "") + isOk = true +} diff --git a/internal/web/actions/default/ns/test/init.go b/internal/web/actions/default/ns/test/init.go new file mode 100644 index 00000000..23f168cb --- /dev/null +++ b/internal/web/actions/default/ns/test/init.go @@ -0,0 +1,20 @@ +package test + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers" + "github.com/iwind/TeaGo" +) + +func init() { + TeaGo.BeforeStart(func(server *TeaGo.Server) { + server. + Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)). + Data("teaMenu", "ns"). + Data("teaSubMenu", "test"). + Prefix("/ns/test"). + GetPost("", new(IndexAction)). + Post("/nodeOptions", new(NodeOptionsAction)). + EndAll() + }) +} diff --git a/internal/web/actions/default/ns/test/nodeOptions.go b/internal/web/actions/default/ns/test/nodeOptions.go new file mode 100644 index 00000000..40665f9c --- /dev/null +++ b/internal/web/actions/default/ns/test/nodeOptions.go @@ -0,0 +1,59 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package test + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" +) + +type NodeOptionsAction struct { + actionutils.ParentAction +} + +func (this *NodeOptionsAction) RunPost(params struct { + ClusterId int64 +}) { + nodesResp, err := this.RPC().NSNodeRPC().FindAllEnabledNSNodesWithNSClusterId(this.AdminContext(), &pb.FindAllEnabledNSNodesWithNSClusterIdRequest{NsClusterId: params.ClusterId}) + if err != nil { + this.ErrorPage(err) + return + } + + var nodeMaps = []maps.Map{} + for _, node := range nodesResp.NsNodes { + if !node.IsOn { + continue + } + + addressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{ + NodeId: node.Id, + Role: nodeconfigs.NodeRoleDNS, + }) + if err != nil { + this.ErrorPage(err) + return + } + var addresses = addressesResp.Addresses + if len(addresses) == 0 { + continue + } + var addrs = []string{} + for _, addr := range addresses { + if addr.CanAccess { + addrs = append(addrs, addr.Ip) + } + } + + nodeMaps = append(nodeMaps, maps.Map{ + "id": node.Id, + "name": node.Name, + "addrs": addrs, + }) + } + this.Data["nodes"] = nodeMaps + + this.Success() +} diff --git a/internal/web/helpers/user_must_auth.go b/internal/web/helpers/user_must_auth.go index c76cb328..be4745bb 100644 --- a/internal/web/helpers/user_must_auth.go +++ b/internal/web/helpers/user_must_auth.go @@ -293,6 +293,11 @@ func (this *userMustAuth) modules(adminId int64) []maps.Map { "url": "/ns/settings", "code": "setting", }, + { + "name": "解析测试", + "url": "/ns/test", + "code": "test", + }, }, }, { diff --git a/internal/web/import.go b/internal/web/import.go index 16786ff6..2582995b 100644 --- a/internal/web/import.go +++ b/internal/web/import.go @@ -51,6 +51,7 @@ import ( _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/logs" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/routes" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/settings/accesslogs" + _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/test" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/users" // 服务相关 diff --git a/web/views/@default/ns/test/index.css b/web/views/@default/ns/test/index.css new file mode 100644 index 00000000..39fe0d2d --- /dev/null +++ b/web/views/@default/ns/test/index.css @@ -0,0 +1,14 @@ +pre.pre-box { + background: #eee; + padding: 1em; +} +.reasons { + margin-top: 0.3em; +} +.reasons ul { + margin: 0; + list-style: none; + padding: 0; + line-height: 1.8; +} +/*# sourceMappingURL=index.css.map */ \ No newline at end of file diff --git a/web/views/@default/ns/test/index.css.map b/web/views/@default/ns/test/index.css.map new file mode 100644 index 00000000..15c271af --- /dev/null +++ b/web/views/@default/ns/test/index.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA,GAAG;EACF,gBAAA;EACA,YAAA;;AAGD;EACC,iBAAA;;AADD,QAGC;EACC,SAAA;EACA,gBAAA;EACA,UAAA;EACA,gBAAA","file":"index.css"} \ No newline at end of file diff --git a/web/views/@default/ns/test/index.html b/web/views/@default/ns/test/index.html new file mode 100644 index 00000000..9d42eb7f --- /dev/null +++ b/web/views/@default/ns/test/index.html @@ -0,0 +1,76 @@ +{$layout} + +
\ No newline at end of file diff --git a/web/views/@default/ns/test/index.js b/web/views/@default/ns/test/index.js new file mode 100644 index 00000000..d36c915b --- /dev/null +++ b/web/views/@default/ns/test/index.js @@ -0,0 +1,51 @@ +Tea.context(function () { + this.clusterId = 0 + if (this.clusters.length > 0) { + this.clusterId = this.clusters[0].id + this.$delay(function () { + this.changeCluster() + }) + } + + this.nodeId = 0 + this.nodes = [] + this.selectedNode = null + + this.isDoing = false + this.result = null + + this.before = function () { + this.isDoing = true + this.result = null + } + + this.success = function (resp) { + this.result = resp.data + } + + this.done = function () { + this.isDoing = false + } + + this.changeCluster = function () { + this.nodeId = 0 + this.$post(".nodeOptions") + .params({ + clusterId: this.clusterId + }) + .success(function (resp) { + this.nodes = resp.data.nodes + if (this.nodes.length > 0) { + this.nodeId = this.nodes[0].id + this.changeNode() + } + }) + } + + this.changeNode = function () { + let that = this + this.selectedNode = this.nodes.$find(function (k, v) { + return v.id == that.nodeId + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/ns/test/index.less b/web/views/@default/ns/test/index.less new file mode 100644 index 00000000..4885cb1a --- /dev/null +++ b/web/views/@default/ns/test/index.less @@ -0,0 +1,15 @@ +pre.pre-box { + background: #eee; + padding: 1em; +} + +.reasons { + margin-top: 0.3em; + + ul { + margin: 0; + list-style: none; + padding: 0; + line-height: 1.8; + } +} \ No newline at end of file