From b6ae2292c324cd48d22e02048805ebe7af73ae56 Mon Sep 17 00:00:00 2001 From: GoEdgeLab Date: Sun, 17 Jan 2021 16:47:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8A=82=E7=82=B9=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E7=8A=B6=E6=80=81=E6=8F=90=E7=A4=BA=E5=92=8C=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/rpc/rpc_client.go | 4 + internal/tasks/task_sync_cluster.go | 37 +-- .../actions/default/clusters/checkChange.go | 37 --- internal/web/actions/default/clusters/init.go | 4 +- internal/web/actions/default/clusters/sync.go | 44 ---- .../actions/default/clusters/tasks/check.go | 23 ++ .../actions/default/clusters/tasks/delete.go | 24 ++ .../actions/default/clusters/tasks/init.go | 22 ++ .../default/clusters/tasks/listPopup.go | 67 ++++++ .../actions/default/nodes/nodeutils/utils.go | 170 +++++++++++++ .../components/waf/ipadmin/createIPPopup.go | 8 - .../components/waf/ipadmin/deleteIP.go | 8 - .../waf/ipadmin/ipadminutils/utils.go | 28 --- .../components/waf/ipadmin/updateIPPopup.go | 8 - internal/web/helpers/user_must_auth.go | 1 + internal/web/import.go | 1 + web/views/@default/@layout.html | 12 + web/views/@default/@layout.js | 223 ++++++++++-------- .../@default/clusters/tasks/listPopup.css | 6 + .../@default/clusters/tasks/listPopup.css.map | 1 + .../@default/clusters/tasks/listPopup.html | 38 +++ .../@default/clusters/tasks/listPopup.js | 31 +++ .../@default/clusters/tasks/listPopup.less | 5 + 23 files changed, 557 insertions(+), 245 deletions(-) delete mode 100644 internal/web/actions/default/clusters/checkChange.go delete mode 100644 internal/web/actions/default/clusters/sync.go create mode 100644 internal/web/actions/default/clusters/tasks/check.go create mode 100644 internal/web/actions/default/clusters/tasks/delete.go create mode 100644 internal/web/actions/default/clusters/tasks/init.go create mode 100644 internal/web/actions/default/clusters/tasks/listPopup.go delete mode 100644 internal/web/actions/default/servers/components/waf/ipadmin/ipadminutils/utils.go create mode 100644 web/views/@default/clusters/tasks/listPopup.css create mode 100644 web/views/@default/clusters/tasks/listPopup.css.map create mode 100644 web/views/@default/clusters/tasks/listPopup.html create mode 100644 web/views/@default/clusters/tasks/listPopup.js create mode 100644 web/views/@default/clusters/tasks/listPopup.less diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index 71ddf800..28884b9b 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -252,6 +252,10 @@ func (this *RPCClient) LoginRPC() pb.LoginServiceClient { return pb.NewLoginServiceClient(this.pickConn()) } +func (this *RPCClient) NodeTaskRPC() pb.NodeTaskServiceClient { + return pb.NewNodeTaskServiceClient(this.pickConn()) +} + // 构造Admin上下文 func (this *RPCClient) Context(adminId int64) context.Context { ctx := context.Background() diff --git a/internal/tasks/task_sync_cluster.go b/internal/tasks/task_sync_cluster.go index 6222d6a8..ff8c1480 100644 --- a/internal/tasks/task_sync_cluster.go +++ b/internal/tasks/task_sync_cluster.go @@ -8,6 +8,7 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" _ "github.com/iwind/TeaGo/bootstrap" + "github.com/iwind/TeaGo/lists" "github.com/iwind/TeaGo/logs" "time" ) @@ -48,24 +49,32 @@ func (this *SyncClusterTask) loop() error { return err } ctx := rpcClient.Context(0) - resp, err := rpcClient.NodeClusterRPC().FindAllChangedNodeClusters(ctx, &pb.FindAllChangedNodeClustersRequest{}) + + tasksResp, err := rpcClient.NodeTaskRPC().FindNotifyingNodeTasks(ctx, &pb.FindNotifyingNodeTasksRequest{Size: 100}) + if err != nil { + return err + } + nodeIds := []int64{} + taskIds := []int64{} + for _, task := range tasksResp.NodeTasks { + if !lists.ContainsInt64(nodeIds, task.Node.Id) { + nodeIds = append(nodeIds, task.Node.Id) + } + taskIds = append(taskIds, task.Id) + } + if len(nodeIds) == 0 { + return nil + } + _, err = nodeutils.SendMessageToNodeIds(ctx, nodeIds, messageconfigs.MessageCodeNewNodeTask, &messageconfigs.NewNodeTaskMessage{}, 3) if err != nil { return err } - for _, cluster := range resp.NodeClusters { - _, err := rpcClient.NodeRPC().SyncNodesVersionWithCluster(ctx, &pb.SyncNodesVersionWithClusterRequest{ - NodeClusterId: cluster.Id, - }) - if err != nil { - return err - } - - // 发送通知 - _, err = nodeutils.SendMessageToCluster(ctx, cluster.Id, messageconfigs.MessageCodeConfigChanged, &messageconfigs.ConfigChangedMessage{}, 10) - if err != nil { - return err - } + // 设置已通知 + _, err = rpcClient.NodeTaskRPC().UpdateNodeTasksNotified(ctx, &pb.UpdateNodeTasksNotifiedRequest{NodeTaskIds: taskIds}) + if err != nil { + return err } + return nil } diff --git a/internal/web/actions/default/clusters/checkChange.go b/internal/web/actions/default/clusters/checkChange.go deleted file mode 100644 index 41823fc6..00000000 --- a/internal/web/actions/default/clusters/checkChange.go +++ /dev/null @@ -1,37 +0,0 @@ -package clusters - -import ( - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" - "github.com/iwind/TeaGo/maps" -) - -// 检查变更的集群列表 -type CheckChangeAction struct { - actionutils.ParentAction -} - -func (this *CheckChangeAction) Init() { - this.Nav("", "", "") -} - -func (this *CheckChangeAction) RunPost(params struct { - IsNotifying bool -}) { - resp, err := this.RPC().NodeClusterRPC().FindAllChangedNodeClusters(this.AdminContext(), &pb.FindAllChangedNodeClustersRequest{}) - if err != nil { - this.ErrorPage(err) - return - } - - result := []maps.Map{} - for _, cluster := range resp.NodeClusters { - result = append(result, maps.Map{ - "id": cluster.Id, - "name": cluster.Name, - }) - } - - this.Data["clusters"] = result - this.Success() -} diff --git a/internal/web/actions/default/clusters/init.go b/internal/web/actions/default/clusters/init.go index ca308978..d4fe830b 100644 --- a/internal/web/actions/default/clusters/init.go +++ b/internal/web/actions/default/clusters/init.go @@ -15,14 +15,12 @@ func init() { Prefix("/clusters"). Get("", new(IndexAction)). GetPost("/create", new(CreateAction)). - Post("/sync", new(SyncAction)). - Post("/checkChange", new(CheckChangeAction)). // 只要登录即可访问的Action EndHelpers(). Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeCommon)). Post("/options", new(OptionsAction)). - + EndAll() }) } diff --git a/internal/web/actions/default/clusters/sync.go b/internal/web/actions/default/clusters/sync.go deleted file mode 100644 index 4e0d2d29..00000000 --- a/internal/web/actions/default/clusters/sync.go +++ /dev/null @@ -1,44 +0,0 @@ -package clusters - -import ( - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" - "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" -) - -// 同步集群 -type SyncAction struct { - actionutils.ParentAction -} - -func (this *SyncAction) RunPost(params struct{}) { - // TODO 将来可以单独选择某一个集群进行单独的同步 - - // 所有有变化的集群 - clustersResp, err := this.RPC().NodeClusterRPC().FindAllChangedNodeClusters(this.AdminContext(), &pb.FindAllChangedNodeClustersRequest{}) - if err != nil { - this.ErrorPage(err) - return - } - clusters := clustersResp.NodeClusters - - for _, cluster := range clusters { - _, err := this.RPC().NodeRPC().SyncNodesVersionWithCluster(this.AdminContext(), &pb.SyncNodesVersionWithClusterRequest{ - NodeClusterId: cluster.Id, - }) - if err != nil { - this.ErrorPage(err) - return - } - - // 发送通知 - _, err = nodeutils.SendMessageToCluster(this.AdminContext(), cluster.Id, messageconfigs.MessageCodeConfigChanged, &messageconfigs.ConfigChangedMessage{}, 10) - if err != nil { - this.ErrorPage(err) - return - } - } - - this.Success() -} diff --git a/internal/web/actions/default/clusters/tasks/check.go b/internal/web/actions/default/clusters/tasks/check.go new file mode 100644 index 00000000..5ca5e4a7 --- /dev/null +++ b/internal/web/actions/default/clusters/tasks/check.go @@ -0,0 +1,23 @@ +package tasks + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type CheckAction struct { + actionutils.ParentAction +} + +func (this *CheckAction) RunPost(params struct{}) { + resp, err := this.RPC().NodeTaskRPC().ExistsNodeTasks(this.AdminContext(), &pb.ExistsNodeTasksRequest{}) + if err != nil { + this.ErrorPage(err) + return + } + + this.Data["isDoing"] = resp.ExistTasks + this.Data["hasError"] = resp.ExistError + + this.Success() +} diff --git a/internal/web/actions/default/clusters/tasks/delete.go b/internal/web/actions/default/clusters/tasks/delete.go new file mode 100644 index 00000000..72a046bd --- /dev/null +++ b/internal/web/actions/default/clusters/tasks/delete.go @@ -0,0 +1,24 @@ +package tasks + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type DeleteAction struct { + actionutils.ParentAction +} + +func (this *DeleteAction) RunPost(params struct { + TaskId int64 +}) { + defer this.CreateLogInfo("删除同步任务 %d", params.TaskId) + + _, err := this.RPC().NodeTaskRPC().DeleteNodeTask(this.AdminContext(), &pb.DeleteNodeTaskRequest{NodeTaskId: params.TaskId}) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/clusters/tasks/init.go b/internal/web/actions/default/clusters/tasks/init.go new file mode 100644 index 00000000..bc9a45e8 --- /dev/null +++ b/internal/web/actions/default/clusters/tasks/init.go @@ -0,0 +1,22 @@ +package tasks + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers" + "github.com/iwind/TeaGo" +) + +func init() { + TeaGo.BeforeStart(func(server *TeaGo.Server) { + server. + Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNode)). + Helper(clusterutils.NewClustersHelper()). + Prefix("/clusters/tasks"). + GetPost("/listPopup", new(ListPopupAction)). + Post("/check", new(CheckAction)). + Post("/delete", new(DeleteAction)). + + EndAll() + }) +} diff --git a/internal/web/actions/default/clusters/tasks/listPopup.go b/internal/web/actions/default/clusters/tasks/listPopup.go new file mode 100644 index 00000000..f0948ecc --- /dev/null +++ b/internal/web/actions/default/clusters/tasks/listPopup.go @@ -0,0 +1,67 @@ +package tasks + +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" + timeutil "github.com/iwind/TeaGo/utils/time" +) + +type ListPopupAction struct { + actionutils.ParentAction +} + +func (this *ListPopupAction) Init() { + this.Nav("", "", "") +} + +func (this *ListPopupAction) RunGet(params struct{}) { + this.retrieveTasks() + + this.Show() +} + +func (this *ListPopupAction) RunPost(params struct { + Must *actions.Must +}) { + this.retrieveTasks() + this.Success() +} + +func (this *ListPopupAction) retrieveTasks() { + resp, err := this.RPC().NodeTaskRPC().FindNodeClusterTasks(this.AdminContext(), &pb.FindNodeClusterTasksRequest{}) + if err != nil { + this.ErrorPage(err) + return + } + + countTasks := 0 + clusterMaps := []maps.Map{} + for _, cluster := range resp.ClusterTasks { + taskMaps := []maps.Map{} + for _, task := range cluster.NodeTasks { + countTasks++ + taskMaps = append(taskMaps, maps.Map{ + "id": task.Id, + "type": task.Type, + "node": maps.Map{ + "id": task.Node.Id, + "name": task.Node.Name, + }, + "isOk": task.IsOk, + "error": task.Error, + "isDone": task.IsDone, + "updatedTime": timeutil.FormatTime("Y-m-d H:i:s", task.UpdatedAt), + }) + } + + clusterMaps = append(clusterMaps, maps.Map{ + "id": cluster.ClusterId, + "name": cluster.ClusterName, + "tasks": taskMaps, + }) + } + this.Data["clusters"] = clusterMaps + this.Data["countTasks"] = countTasks +} diff --git a/internal/web/actions/default/nodes/nodeutils/utils.go b/internal/web/actions/default/nodes/nodeutils/utils.go index c697e87c..606bf525 100644 --- a/internal/web/actions/default/nodes/nodeutils/utils.go +++ b/internal/web/actions/default/nodes/nodeutils/utils.go @@ -47,6 +47,176 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg wg := &sync.WaitGroup{} wg.Add(len(nodes)) for _, node := range nodes { + // TODO 检查是否在线 + + if len(node.ConnectedAPINodeIds) == 0 { + locker.Lock() + results = append(results, &MessageResult{ + NodeId: node.Id, + NodeName: node.Name, + IsOK: false, + Message: "节点尚未连接到API", + }) + locker.Unlock() + wg.Done() + continue + } + + // 获取API节点信息 + apiNodeId := node.ConnectedAPINodeIds[0] + rpcClient, ok := rpcMap[apiNodeId] + if !ok { + apiNodeResp, err := defaultRPCClient.APINodeRPC().FindEnabledAPINode(ctx, &pb.FindEnabledAPINodeRequest{NodeId: apiNodeId}) + if err != nil { + locker.Lock() + results = append(results, &MessageResult{ + NodeId: node.Id, + NodeName: node.Name, + IsOK: false, + Message: "无法读取对应的API节点信息:" + err.Error(), + }) + locker.Unlock() + wg.Done() + continue + } + + if apiNodeResp.Node == nil { + locker.Lock() + results = append(results, &MessageResult{ + NodeId: node.Id, + NodeName: node.Name, + IsOK: false, + Message: "无法读取对应的API节点信息:API节点ID:" + strconv.FormatInt(apiNodeId, 10), + }) + locker.Unlock() + wg.Done() + continue + } + apiNode := apiNodeResp.Node + + apiRPCClient, err := rpc.NewRPCClient(&configs.APIConfig{ + RPC: struct { + Endpoints []string `yaml:"endpoints"` + }{ + Endpoints: apiNode.AccessAddrs, + }, + NodeId: apiNode.UniqueId, + Secret: apiNode.Secret, + }) + if err != nil { + locker.Lock() + results = append(results, &MessageResult{ + NodeId: node.Id, + NodeName: node.Name, + IsOK: false, + Message: "初始化API节点错误:API节点ID:" + strconv.FormatInt(apiNodeId, 10) + ":" + err.Error(), + }) + locker.Unlock() + wg.Done() + continue + } + rpcMap[apiNodeId] = apiRPCClient + rpcClient = apiRPCClient + } + + // 发送消息 + go func(node *pb.Node) { + defer wg.Done() + + result, err := rpcClient.NodeRPC().SendCommandToNode(ctx, &pb.NodeStreamMessage{ + NodeId: node.Id, + TimeoutSeconds: timeoutSeconds, + Code: code, + DataJSON: msgJSON, + }) + if err != nil { + locker.Lock() + results = append(results, &MessageResult{ + NodeId: node.Id, + NodeName: node.Name, + IsOK: false, + Message: "API返回错误:" + err.Error(), + }) + locker.Unlock() + return + } + + locker.Lock() + results = append(results, &MessageResult{ + NodeId: node.Id, + NodeName: node.Name, + IsOK: result.IsOk, + Message: result.Message, + }) + locker.Unlock() + }(node) + } + wg.Wait() + + return +} + +// 向一组节点发送命令消息 +func SendMessageToNodeIds(ctx context.Context, nodeIds []int64, code string, msg interface{}, timeoutSeconds int32) (results []*MessageResult, err error) { + results = []*MessageResult{} + if len(nodeIds) == 0 { + return + } + + msgJSON, err := json.Marshal(msg) + if err != nil { + return results, err + } + + defaultRPCClient, err := rpc.SharedRPC() + if err != nil { + return results, err + } + + // 获取所有节点 + nodesResp, err := defaultRPCClient.NodeRPC().FindEnabledNodesWithIds(ctx, &pb.FindEnabledNodesWithIdsRequest{NodeIds: nodeIds}) + if err != nil { + return nil, err + } + nodes := nodesResp.Nodes + if len(nodes) == 0 { + return results, nil + } + + rpcMap := map[int64]*rpc.RPCClient{} // apiNodeId => RPCClient + locker := &sync.Mutex{} + + wg := &sync.WaitGroup{} + wg.Add(len(nodes)) + for _, node := range nodes { + if !node.IsActive { + locker.Lock() + results = append(results, &MessageResult{ + NodeId: node.Id, + NodeName: node.Name, + IsOK: false, + Message: "节点不在线", + }) + locker.Unlock() + wg.Done() + continue + } + + if !node.IsOn { + if !node.IsActive { + locker.Lock() + results = append(results, &MessageResult{ + NodeId: node.Id, + NodeName: node.Name, + IsOK: false, + Message: "节点未启用", + }) + locker.Unlock() + wg.Done() + continue + } + } + if len(node.ConnectedAPINodeIds) == 0 { locker.Lock() results = append(results, &MessageResult{ diff --git a/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go b/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go index e05fc4c4..fcef1be7 100644 --- a/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go +++ b/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go @@ -4,7 +4,6 @@ import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/utils" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/waf/ipadmin/ipadminutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" @@ -83,13 +82,6 @@ func (this *CreateIPPopupAction) RunPost(params struct { } itemId := createResp.IpItemId - // 发送通知 - err = ipadminutils.NotifyUpdateToClustersWithFirewallPolicyId(this.AdminContext(), params.FirewallPolicyId) - if err != nil { - this.ErrorPage(err) - return - } - // 日志 defer this.CreateLog(oplogs.LevelInfo, "在WAF策略 %d 名单中添加IP %d", params.FirewallPolicyId, itemId) diff --git a/internal/web/actions/default/servers/components/waf/ipadmin/deleteIP.go b/internal/web/actions/default/servers/components/waf/ipadmin/deleteIP.go index e2749313..a5cf1dc2 100644 --- a/internal/web/actions/default/servers/components/waf/ipadmin/deleteIP.go +++ b/internal/web/actions/default/servers/components/waf/ipadmin/deleteIP.go @@ -3,7 +3,6 @@ package ipadmin import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/waf/ipadmin/ipadminutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" ) @@ -26,12 +25,5 @@ func (this *DeleteIPAction) RunPost(params struct { return } - // 发送通知 - err = ipadminutils.NotifyUpdateToClustersWithFirewallPolicyId(this.AdminContext(), params.FirewallPolicyId) - if err != nil { - this.ErrorPage(err) - return - } - this.Success() } diff --git a/internal/web/actions/default/servers/components/waf/ipadmin/ipadminutils/utils.go b/internal/web/actions/default/servers/components/waf/ipadmin/ipadminutils/utils.go deleted file mode 100644 index a8d07dd1..00000000 --- a/internal/web/actions/default/servers/components/waf/ipadmin/ipadminutils/utils.go +++ /dev/null @@ -1,28 +0,0 @@ -package ipadminutils - -import ( - "context" - "github.com/TeaOSLab/EdgeAdmin/internal/rpc" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" - "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" -) - -// 通知使用此WAF策略的集群更新 -func NotifyUpdateToClustersWithFirewallPolicyId(ctx context.Context, firewallPolicyId int64) error { - client, err := rpc.SharedRPC() - if err != nil { - return err - } - resp, err := client.NodeClusterRPC().FindAllEnabledNodeClustersWithHTTPFirewallPolicyId(ctx, &pb.FindAllEnabledNodeClustersWithHTTPFirewallPolicyIdRequest{HttpFirewallPolicyId: firewallPolicyId}) - if err != nil { - return err - } - for _, cluster := range resp.NodeClusters { - _, err = nodeutils.SendMessageToCluster(ctx, cluster.Id, messageconfigs.MessageCodeIPListChanged, &messageconfigs.IPListChangedMessage{}, 3) - if err != nil { - return err - } - } - return nil -} diff --git a/internal/web/actions/default/servers/components/waf/ipadmin/updateIPPopup.go b/internal/web/actions/default/servers/components/waf/ipadmin/updateIPPopup.go index 41aa2a1a..525d4b62 100644 --- a/internal/web/actions/default/servers/components/waf/ipadmin/updateIPPopup.go +++ b/internal/web/actions/default/servers/components/waf/ipadmin/updateIPPopup.go @@ -4,7 +4,6 @@ import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/utils" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/waf/ipadmin/ipadminutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/maps" @@ -95,12 +94,5 @@ func (this *UpdateIPPopupAction) RunPost(params struct { return } - // 发送通知 - err = ipadminutils.NotifyUpdateToClustersWithFirewallPolicyId(this.AdminContext(), params.FirewallPolicyId) - if err != nil { - this.ErrorPage(err) - return - } - this.Success() } diff --git a/internal/web/helpers/user_must_auth.go b/internal/web/helpers/user_must_auth.go index 7d33ce03..ef0dffef 100644 --- a/internal/web/helpers/user_must_auth.go +++ b/internal/web/helpers/user_must_auth.go @@ -110,6 +110,7 @@ func (this *userMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam if !action.Data.Has("teaSubMenu") { action.Data["teaSubMenu"] = "" } + action.Data["teaCheckClusterTask"] = configloaders.AllowModule(adminId, configloaders.AdminModuleCodeNode) // 菜单 action.Data["firstMenuItem"] = "" diff --git a/internal/web/import.go b/internal/web/import.go index 8c0a8e3f..f31265a1 100644 --- a/internal/web/import.go +++ b/internal/web/import.go @@ -12,6 +12,7 @@ import ( _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions/items" + _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/tasks" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/csrf" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dashboard" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/db" diff --git a/web/views/@default/@layout.html b/web/views/@default/@layout.html index 1966437a..cd4feac5 100644 --- a/web/views/@default/@layout.html +++ b/web/views/@default/@layout.html @@ -27,12 +27,24 @@ diff --git a/web/views/@default/@layout.js b/web/views/@default/@layout.js index 2c5fe35a..bdefa012 100644 --- a/web/views/@default/@layout.js +++ b/web/views/@default/@layout.js @@ -1,119 +1,152 @@ Tea.context(function () { - this.moreOptionsVisible = false - this.globalMessageBadge = 0 + this.moreOptionsVisible = false + this.globalMessageBadge = 0 - if (typeof this.leftMenuItemIsDisabled == "undefined") { - this.leftMenuItemIsDisabled = false - } + if (typeof this.leftMenuItemIsDisabled == "undefined") { + this.leftMenuItemIsDisabled = false + } - this.$delay(function () { - if (this.$refs.focus != null) { - this.$refs.focus.focus() - } + this.$delay(function () { + if (this.$refs.focus != null) { + this.$refs.focus.focus() + } - // 检查消息 - this.checkMessages() - }) + // 检查消息 + this.checkMessages() - /** - * 左侧子菜单 - */ - this.showSubMenu = function (menu) { - if (menu.alwaysActive) { - return - } - if (this.teaSubMenus.menus != null && this.teaSubMenus.menus.length > 0) { - this.teaSubMenus.menus.$each(function (k, v) { - if (menu.id == v.id) { - return - } - v.isActive = false - }) - } - menu.isActive = !menu.isActive - }; + // 检查集群节点同步 + this.loadNodeTasks(); + }) - /** - * 检查消息 - */ - this.checkMessages = function () { - this.$post("/messages/badge") - .params({}) - .success(function (resp) { - this.globalMessageBadge = resp.data.count - }) - .done(function () { - let delay = 6000 - if (this.globalMessageBadge > 0) { - delay = 30000 - } - this.$delay(function () { - this.checkMessages() - }, delay) - }) - } + /** + * 左侧子菜单 + */ + this.showSubMenu = function (menu) { + if (menu.alwaysActive) { + return + } + if (this.teaSubMenus.menus != null && this.teaSubMenus.menus.length > 0) { + this.teaSubMenus.menus.$each(function (k, v) { + if (menu.id == v.id) { + return + } + v.isActive = false + }) + } + menu.isActive = !menu.isActive + }; - /** - * 底部伸展框 - */ - this.showQQGroupQrcode = function () { - teaweb.popup("/about/qq", { - width: "21em", - height: "24em" - }) - } + /** + * 检查消息 + */ + this.checkMessages = function () { + this.$post("/messages/badge") + .params({}) + .success(function (resp) { + this.globalMessageBadge = resp.data.count + }) + .done(function () { + let delay = 6000 + if (this.globalMessageBadge > 0) { + delay = 30000 + } + this.$delay(function () { + this.checkMessages() + }, delay) + }) + } - /** - * 弹窗中默认成功回调 - */ - if (window.IS_POPUP === true) { - this.success = window.NotifyPopup - } + /** + * 底部伸展框 + */ + this.showQQGroupQrcode = function () { + teaweb.popup("/about/qq", { + width: "21em", + height: "24em" + }) + } + + /** + * 弹窗中默认成功回调 + */ + if (window.IS_POPUP === true) { + this.success = window.NotifyPopup + } + + /** + * 节点同步任务 + */ + this.doingNodeTasks = { + isDoing: false, + hasError: false, + isUpdated: false + } + + this.loadNodeTasks = function () { + this.$post("/clusters/tasks/check") + .success(function (resp) { + this.doingNodeTasks.isDoing = resp.data.isDoing + this.doingNodeTasks.hasError = resp.data.hasError + this.doingNodeTasks.isUpdated = true + }) + .done(function () { + this.$delay(function () { + this.loadNodeTasks() + }, 5000) + }) + } + + this.showNodeTasks = function () { + teaweb.popup("/clusters/tasks/listPopup", { + height: "24em", + width: "50em" + }) + } }); window.NotifySuccess = function (message, url, params) { - if (typeof (url) == "string" && url.length > 0) { - if (url[0] != "/") { - url = Tea.url(url, params); - } - } - return function () { - teaweb.success(message, function () { - window.location = url; - }); - }; + if (typeof (url) == "string" && url.length > 0) { + if (url[0] != "/") { + url = Tea.url(url, params); + } + } + return function () { + teaweb.success(message, function () { + window.location = url; + }); + }; }; window.NotifyReloadSuccess = function (message) { - return function () { - teaweb.success(message, function () { - window.location.reload() - }) - } + return function () { + teaweb.success(message, function () { + window.location.reload() + }) + } } window.NotifyDelete = function (message, url, params) { - teaweb.confirm(message, function () { - Tea.Vue.$post(url) - .params(params) - .refresh(); - }); + teaweb.confirm(message, function () { + Tea.Vue.$post(url) + .params(params) + .refresh(); + }); }; window.NotifyPopup = function (resp) { - window.parent.teaweb.popupFinish(resp); + window.parent.teaweb.popupFinish(resp); }; window.ChangePageSize = function (size) { - let url = window.location.toString(); - if (url.indexOf("pageSize") > 0) { - url = url.replace(/pageSize=\d+/g, "pageSize=" + size); - } else { - if (url.indexOf("?") > 0) { - url += "&pageSize=" + size; - } else { - url += "?pageSize=" + size; - } - } - window.location = url; + let url = window.location.toString(); + if (url.indexOf("pageSize") > 0) { + url = url.replace(/pageSize=\d+/g, "pageSize=" + size); + } else { + if (url.indexOf("?") > 0) { + url += "&pageSize=" + size; + } else { + url += "?pageSize=" + size; + } + } + window.location = url; }; \ No newline at end of file diff --git a/web/views/@default/clusters/tasks/listPopup.css b/web/views/@default/clusters/tasks/listPopup.css new file mode 100644 index 00000000..545fa423 --- /dev/null +++ b/web/views/@default/clusters/tasks/listPopup.css @@ -0,0 +1,6 @@ +h3 span { + margin-left: 0.5em; + color: grey; + font-size: 0.6em !important; +} +/*# sourceMappingURL=listPopup.css.map */ \ No newline at end of file diff --git a/web/views/@default/clusters/tasks/listPopup.css.map b/web/views/@default/clusters/tasks/listPopup.css.map new file mode 100644 index 00000000..a1614f7c --- /dev/null +++ b/web/views/@default/clusters/tasks/listPopup.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["listPopup.less"],"names":[],"mappings":"AAAA,EAAG;EACF,kBAAA;EACA,WAAA;EACA,2BAAA","file":"listPopup.css"} \ No newline at end of file diff --git a/web/views/@default/clusters/tasks/listPopup.html b/web/views/@default/clusters/tasks/listPopup.html new file mode 100644 index 00000000..71d58d38 --- /dev/null +++ b/web/views/@default/clusters/tasks/listPopup.html @@ -0,0 +1,38 @@ +{$layout "layout_popup"} + +

正在同步的任务(共{{countTasks}}个)

+

暂时没有同步的集群。

+
+ + + + + + + + + + + + + + + + + + + + + +
集群节点任务状态触发时间
{{cluster.name}} + {{task.node.name}}   + + 同步配置 + 同步IP名单 + + {{task.error}} + 正在同步... + {{task.updatedTime}} + +
+
\ No newline at end of file diff --git a/web/views/@default/clusters/tasks/listPopup.js b/web/views/@default/clusters/tasks/listPopup.js new file mode 100644 index 00000000..38e06086 --- /dev/null +++ b/web/views/@default/clusters/tasks/listPopup.js @@ -0,0 +1,31 @@ +Tea.context(function () { + this.$delay(function () { + this.reload() + }) + + this.reload = function () { + this.$post("$") + .success(function (resp) { + this.countTasks = resp.data.countTasks + this.clusters = resp.data.clusters + }) + .done(function () { + this.$delay(function () { + this.reload() + }, 5000) + }) + } + + this.deleteTask = function (taskId) { + let that = this + teaweb.confirm("确定要删除这个任务吗?", function () { + that.$post(".delete") + .params({ + taskId: taskId + }) + .success(function () { + teaweb.reload() + }) + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/clusters/tasks/listPopup.less b/web/views/@default/clusters/tasks/listPopup.less new file mode 100644 index 00000000..19113e8d --- /dev/null +++ b/web/views/@default/clusters/tasks/listPopup.less @@ -0,0 +1,5 @@ +h3 span { + margin-left: 0.5em; + color: grey; + font-size: 0.6em !important; +}