diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index 50c9144b..c3672f6e 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -71,6 +71,10 @@ func (this *RPCClient) NodeGrantRPC() pb.NodeGrantServiceClient { return pb.NewNodeGrantServiceClient(this.pickConn()) } +func (this *RPCClient) NodeLoginRPC() pb.NodeLoginServiceClient { + return pb.NewNodeLoginServiceClient(this.pickConn()) +} + func (this *RPCClient) NodeClusterRPC() pb.NodeClusterServiceClient { return pb.NewNodeClusterServiceClient(this.pickConn()) } diff --git a/internal/web/actions/default/clusters/cluster/createNode.go b/internal/web/actions/default/clusters/cluster/createNode.go index 8d844e14..ebe84ed9 100644 --- a/internal/web/actions/default/clusters/cluster/createNode.go +++ b/internal/web/actions/default/clusters/cluster/createNode.go @@ -4,11 +4,13 @@ import ( "encoding/json" "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils" "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/maps" "strconv" + "strings" ) // CreateNodeAction 创建节点 @@ -67,6 +69,22 @@ func (this *CreateNodeAction) RunGet(params struct { } this.Data["dnsRoutes"] = dnsRouteMaps + // API节点列表 + apiNodesResp, err := this.RPC().APINodeRPC().FindAllEnabledAPINodes(this.AdminContext(), &pb.FindAllEnabledAPINodesRequest{}) + if err != nil { + this.ErrorPage(err) + return + } + apiNodes := apiNodesResp.Nodes + apiEndpoints := []string{} + for _, apiNode := range apiNodes { + if !apiNode.IsOn { + continue + } + apiEndpoints = append(apiEndpoints, apiNode.AccessAddrs...) + } + this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\"" + this.Show() } @@ -174,5 +192,56 @@ func (this *CreateNodeAction) RunPost(params struct { // 创建日志 defer this.CreateLog(oplogs.LevelInfo, "创建节点 %d", nodeId) + // 响应数据 + this.Data["nodeId"] = nodeId + nodeResp, err := this.RPC().NodeRPC().FindEnabledNode(this.AdminContext(), &pb.FindEnabledNodeRequest{NodeId: nodeId}) + if err != nil { + this.ErrorPage(err) + return + } + if nodeResp.Node != nil { + var addresses = []string{} + for _, addrMap := range ipAddresses { + addresses = append(addresses, addrMap.GetString("ip")) + } + + var grantMap maps.Map = nil + grantId := params.GrantId + if grantId > 0 { + grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId}) + if err != nil { + this.ErrorPage(err) + return + } + if grantResp.NodeGrant != nil && grantResp.NodeGrant.Id > 0 { + grantMap = maps.Map{ + "id": grantResp.NodeGrant.Id, + "name": grantResp.NodeGrant.Name, + "method": grantResp.NodeGrant.Method, + "methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method), + } + } + } + + this.Data["node"] = maps.Map{ + "id": nodeResp.Node.Id, + "name": nodeResp.Node.Name, + "uniqueId": nodeResp.Node.UniqueId, + "secret": nodeResp.Node.Secret, + "addresses": addresses, + "login": maps.Map{ + "id": 0, + "name": "SSH", + "type": "ssh", + "params": maps.Map{ + "grantId": params.GrantId, + "host": params.SshHost, + "port": params.SshPort, + }, + }, + "grant": grantMap, + } + } + this.Success() } diff --git a/internal/web/actions/default/clusters/cluster/createNodeInstall.go b/internal/web/actions/default/clusters/cluster/createNodeInstall.go new file mode 100644 index 00000000..16cf73c5 --- /dev/null +++ b/internal/web/actions/default/clusters/cluster/createNodeInstall.go @@ -0,0 +1,76 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cluster + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/maps" +) + +type CreateNodeInstallAction struct { + actionutils.ParentAction +} + +func (this *CreateNodeInstallAction) RunPost(params struct { + NodeId int64 + SshHost string + SshPort int + GrantId int64 + + Must *actions.Must +}) { + defer this.CreateLogInfo("安装节点 %d", params.NodeId) + + params.Must. + Field("sshHost2", params.SshHost). + Require("请填写SSH主机地址"). + Field("sshPort2", params.SshPort). + Gt(0, "请填写SSH主机端口"). + Lt(65535, "SSH主机端口需要小于65535"). + Field("grantId", params.GrantId). + Gt(0, "请选择SSH登录认证") + + // 查询login + nodeResp, err := this.RPC().NodeRPC().FindEnabledNode(this.AdminContext(), &pb.FindEnabledNodeRequest{NodeId: params.NodeId}) + if err != nil { + this.ErrorPage(err) + return + } + var node = nodeResp.Node + if node == nil { + this.Fail("找不到要修改的节点") + } + var loginId int64 + if node.NodeLogin != nil { + loginId = node.NodeLogin.Id + } + + // 修改节点信息 + _, err = this.RPC().NodeRPC().UpdateNodeLogin(this.AdminContext(), &pb.UpdateNodeLoginRequest{ + NodeId: params.NodeId, + NodeLogin: &pb.NodeLogin{ + Id: loginId, + Name: "SSH", + Type: "ssh", + Params: maps.Map{ + "grantId": params.GrantId, + "host": params.SshHost, + "port": params.SshPort, + }.AsJSON(), + }, + }) + if err != nil { + this.ErrorPage(err) + return + } + + // 开始安装 + _, err = this.RPC().NodeRPC().InstallNode(this.AdminContext(), &pb.InstallNodeRequest{NodeId: params.NodeId}) + if err != nil { + this.Fail("安装失败:" + err.Error()) + } + + this.Success() +} diff --git a/internal/web/actions/default/clusters/cluster/init.go b/internal/web/actions/default/clusters/cluster/init.go index 6499fb57..34fce311 100644 --- a/internal/web/actions/default/clusters/cluster/init.go +++ b/internal/web/actions/default/clusters/cluster/init.go @@ -27,9 +27,11 @@ func init() { Post("/upgradeStatus", new(UpgradeStatusAction)). GetPost("/delete", new(DeleteAction)). GetPost("/createNode", new(CreateNodeAction)). + Post("/createNodeInstall", new(CreateNodeInstallAction)). GetPost("/createBatch", new(CreateBatchAction)). GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)). GetPost("/installManual", new(InstallManualAction)). + Post("/suggestLoginPorts", new(SuggestLoginPortsAction)). // 节点相关 Prefix("/clusters/cluster/node"). @@ -58,7 +60,6 @@ func init() { // 看板相关 Prefix("/clusters/cluster/boards"). Get("", new(boards.IndexAction)). - EndAll() }) } diff --git a/internal/web/actions/default/clusters/cluster/node/install.go b/internal/web/actions/default/clusters/cluster/node/install.go index 2d1b6920..78936350 100644 --- a/internal/web/actions/default/clusters/cluster/node/install.go +++ b/internal/web/actions/default/clusters/cluster/node/install.go @@ -9,7 +9,7 @@ import ( "strings" ) -// 安装节点 +// InstallAction 安装节点 type InstallAction struct { actionutils.ParentAction } @@ -97,7 +97,7 @@ func (this *InstallAction) RunGet(params struct { this.Show() } -// 开始安装 +// RunPost 开始安装 func (this *InstallAction) RunPost(params struct { NodeId int64 diff --git a/internal/web/actions/default/clusters/cluster/suggestLoginPorts.go b/internal/web/actions/default/clusters/cluster/suggestLoginPorts.go new file mode 100644 index 00000000..65cac27a --- /dev/null +++ b/internal/web/actions/default/clusters/cluster/suggestLoginPorts.go @@ -0,0 +1,36 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cluster + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type SuggestLoginPortsAction struct { + actionutils.ParentAction +} + +func (this *SuggestLoginPortsAction) RunPost(params struct { + Host string +}) { + portsResp, err := this.RPC().NodeLoginRPC().FindNodeLoginSuggestPorts(this.AdminContext(), &pb.FindNodeLoginSuggestPortsRequest{Host: params.Host}) + if err != nil { + this.ErrorPage(err) + return + } + + if len(portsResp.Ports) == 0 { + this.Data["ports"] = []int32{} + } else { + this.Data["ports"] = portsResp.Ports + } + + if len(portsResp.AvailablePorts) == 0 { + this.Data["availablePorts"] = []int32{} + } else { + this.Data["availablePorts"] = portsResp.AvailablePorts + } + + this.Success() +} diff --git a/web/public/js/components/grant/grant-selector.js b/web/public/js/components/grant/grant-selector.js index a3019667..746483da 100644 --- a/web/public/js/components/grant/grant-selector.js +++ b/web/public/js/components/grant/grant-selector.js @@ -16,21 +16,24 @@ Vue.component("grant-selector", { if (that.grantId > 0) { that.grant = resp.data.grant; } + that.notifyUpdate() } - }); + }) }, // 创建授权 create: function () { + let that = this teaweb.popup("/clusters/grants/createPopup", { height: "26em", callback: (resp) => { - this.grantId = resp.data.grant.id; - if (this.grantId > 0) { - this.grant = resp.data.grant; + that.grantId = resp.data.grant.id; + if (that.grantId > 0) { + that.grant = resp.data.grant; } + that.notifyUpdate() } - }); + }) }, // 修改授权 @@ -39,18 +42,24 @@ Vue.component("grant-selector", { window.location.reload(); return; } + let that = this teaweb.popup("/clusters/grants/updatePopup?grantId=" + this.grant.id, { height: "26em", callback: (resp) => { - this.grant = resp.data.grant; + that.grant = resp.data.grant + that.notifyUpdate() } }) }, // 删除已选择授权 remove: function () { - this.grant = null; - this.grantId = 0; + this.grant = null + this.grantId = 0 + this.notifyUpdate() + }, + notifyUpdate: function () { + this.$emit("change", this.grant) } }, template: `