可以在创建、修改节点的时候选择分组,可以根据分组筛选节点

This commit is contained in:
刘祥超
2020-10-28 20:00:27 +08:00
parent cd4f4c41f6
commit 181976f79f
21 changed files with 310 additions and 33 deletions

View File

@@ -42,6 +42,7 @@ func (this *CreateBatchAction) RunGet(params struct {
func (this *CreateBatchAction) RunPost(params struct {
ClusterId int64
GroupId int64
IpList string
Must *actions.Must
@@ -76,6 +77,7 @@ func (this *CreateBatchAction) RunPost(params struct {
resp, err := this.RPC().NodeRPC().CreateNode(this.AdminContext(), &pb.CreateNodeRequest{
Name: ip,
ClusterId: params.ClusterId,
GroupId: params.GroupId,
Login: nil,
})
if err != nil {

View File

@@ -43,6 +43,7 @@ func (this *CreateNodeAction) RunPost(params struct {
Name string
IpAddressesJSON []byte
ClusterId int64
GroupId int64
GrantId int64
SshHost string
SshPort int
@@ -78,6 +79,7 @@ func (this *CreateNodeAction) RunPost(params struct {
createResp, err := this.RPC().NodeRPC().CreateNode(this.AdminContext(), &pb.CreateNodeRequest{
Name: params.Name,
ClusterId: params.ClusterId,
GroupId: params.GroupId,
Login: loginInfo,
})
if err != nil {

View File

@@ -4,6 +4,7 @@ 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 CreatePopupAction struct {
@@ -31,7 +32,7 @@ func (this *CreatePopupAction) RunPost(params struct {
params.Must.
Field("name", params.Name).
Require("请输入分组名称")
_, err := this.RPC().NodeGroupRPC().CreateNodeGroup(this.AdminContext(), &pb.CreateNodeGroupRequest{
createResp, err := this.RPC().NodeGroupRPC().CreateNodeGroup(this.AdminContext(), &pb.CreateNodeGroupRequest{
ClusterId: params.ClusterId,
Name: params.Name,
})
@@ -40,5 +41,10 @@ func (this *CreatePopupAction) RunPost(params struct {
return
}
this.Data["group"] = maps.Map{
"id": createResp.GroupId,
"name": params.Name,
}
this.Success()
}

View File

@@ -0,0 +1,31 @@
package groups
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type OptionsAction struct {
actionutils.ParentAction
}
func (this *OptionsAction) RunPost(params struct {
ClusterId int64
}) {
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithClusterIdRequest{ClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
}
groupMaps := []maps.Map{}
for _, group := range groupsResp.Groups {
groupMaps = append(groupMaps, maps.Map{
"id": group.Id,
"name": group.Name,
})
}
this.Data["groups"] = groupMaps
this.Success()
}

View File

@@ -0,0 +1,64 @@
package groups
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 SelectPopupAction struct {
actionutils.ParentAction
}
func (this *SelectPopupAction) Init() {
this.Nav("", "", "")
}
func (this *SelectPopupAction) RunGet(params struct {
ClusterId int64
}) {
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithClusterIdRequest{ClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
}
groupMaps := []maps.Map{}
for _, group := range groupsResp.Groups {
groupMaps = append(groupMaps, maps.Map{
"id": group.Id,
"name": group.Name,
})
}
this.Data["groups"] = groupMaps
this.Show()
}
func (this *SelectPopupAction) RunPost(params struct {
GroupId int64
Must *actions.Must
}) {
if params.GroupId <= 0 {
this.Fail("请选择要使用的分组")
}
groupResp, err := this.RPC().NodeGroupRPC().FindEnabledNodeGroup(this.AdminContext(), &pb.FindEnabledNodeGroupRequest{GroupId: params.GroupId})
if err != nil {
this.ErrorPage(err)
return
}
group := groupResp.Group
if group == nil {
this.NotFound("nodeGroup", params.GroupId)
return
}
this.Data["group"] = maps.Map{
"id": group.Id,
"name": group.Name,
}
this.Success()
}

View File

@@ -23,16 +23,19 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ClusterId int64
GroupId int64
InstalledState int
ActiveState int
Keyword string
}) {
this.Data["groupId"] = params.GroupId
this.Data["installState"] = params.InstalledState
this.Data["activeState"] = params.ActiveState
this.Data["keyword"] = params.Keyword
countResp, err := this.RPC().NodeRPC().CountAllEnabledNodesMatch(this.AdminContext(), &pb.CountAllEnabledNodesMatchRequest{
ClusterId: params.ClusterId,
GroupId: params.GroupId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
@@ -49,6 +52,7 @@ func (this *IndexAction) RunGet(params struct {
Offset: page.Offset,
Size: page.Size,
ClusterId: params.ClusterId,
GroupId: params.GroupId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
@@ -84,6 +88,14 @@ func (this *IndexAction) RunGet(params struct {
})
}
var groupMap maps.Map = nil
if node.Group != nil {
groupMap = maps.Map{
"id": node.Group.Id,
"name": node.Group.Name,
}
}
nodeMaps = append(nodeMaps, maps.Map{
"id": node.Id,
"name": node.Name,
@@ -110,9 +122,35 @@ func (this *IndexAction) RunGet(params struct {
},
"isSynced": isSynced,
"ipAddresses": ipAddresses,
"group": groupMap,
})
}
this.Data["nodes"] = nodeMaps
// 所有分组
groupMaps := []maps.Map{}
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithClusterIdRequest{
ClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
for _, group := range groupsResp.Groups {
countResp, err := this.RPC().NodeRPC().CountAllEnabledNodesWithGroupId(this.AdminContext(), &pb.CountAllEnabledNodesWithGroupIdRequest{GroupId: group.Id})
if err != nil {
this.ErrorPage(err)
return
}
countNodes := countResp.Count
groupMaps = append(groupMaps, maps.Map{
"id": group.Id,
"name": group.Name,
"countNodes": countNodes,
})
}
this.Data["groups"] = groupMaps
this.Show()
}

View File

@@ -42,6 +42,8 @@ func init() {
GetPost("/groups/updatePopup", new(groups.UpdatePopupAction)).
Post("/groups/delete", new(groups.DeleteAction)).
Post("/groups/sort", new(groups.SortAction)).
Post("/groups/options", new(groups.OptionsAction)).
GetPost("/groups/selectPopup", new(groups.SelectPopupAction)).
EndAll()
})

View File

@@ -120,6 +120,14 @@ func (this *NodeAction) RunGet(params struct {
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
}
var groupMap maps.Map = nil
if node.Group != nil {
groupMap = maps.Map{
"id": node.Group.Id,
"name": node.Group.Name,
}
}
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
@@ -142,6 +150,8 @@ func (this *NodeAction) RunGet(params struct {
"memUsage": status.MemoryUsage,
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
},
"group": groupMap,
}
this.Show()

View File

@@ -98,6 +98,14 @@ func (this *UpdateAction) RunGet(params struct {
}
}
var groupMap maps.Map = nil
if node.Group != nil {
groupMap = maps.Map{
"id": node.Group.Id,
"name": node.Group.Name,
}
}
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
@@ -106,6 +114,7 @@ func (this *UpdateAction) RunGet(params struct {
"login": loginMap,
"maxCPU": node.MaxCPU,
"isOn": node.IsOn,
"group": groupMap,
}
// 所有集群
@@ -132,6 +141,7 @@ func (this *UpdateAction) RunGet(params struct {
func (this *UpdateAction) RunPost(params struct {
LoginId int64
NodeId int64
GroupId int64
Name string
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
ClusterId int64
@@ -171,6 +181,7 @@ func (this *UpdateAction) RunPost(params struct {
// 保存
_, err := this.RPC().NodeRPC().UpdateNode(this.AdminContext(), &pb.UpdateNodeRequest{
NodeId: params.NodeId,
GroupId: params.GroupId,
Name: params.Name,
ClusterId: params.ClusterId,
Login: loginInfo,

View File

@@ -0,0 +1,50 @@
Vue.component("node-group-selector", {
props: ["v-cluster-id", "v-group"],
mounted: function () {
let that = this
Tea.action("/clusters/cluster/groups/options")
.post()
.params({
clusterId: this.vClusterId
})
.success(function (resp) {
})
},
data: function () {
return {
groups: [],
selectedGroup: this.vGroup,
}
},
methods: {
selectGroup: function () {
let that = this
teaweb.popup("/clusters/cluster/groups/selectPopup?clusterId=" + this.vClusterId, {
callback: function (resp) {
that.selectedGroup = resp.data.group
}
})
},
addGroup: function () {
let that = this
teaweb.popup("/clusters/cluster/groups/createPopup?clusterId=" + this.vClusterId, {
callback: function (resp) {
that.selectedGroup = resp.data.group
}
})
},
removeGroup: function () {
this.selectedGroup = null
}
},
template: `<div>
<div class="ui label tiny" v-if="selectedGroup != null">
<input type="hidden" name="groupId" :value="selectedGroup.id"/>
{{selectedGroup.name}} &nbsp;<a href="" title="删除" @click.prevent="removeGroup()"><i class="icon remove"></i></a>
</div>
<div v-if="selectedGroup == null">
<a href="" @click.prevent="selectGroup()">[选择分组]</a> &nbsp; <a href="" @click.prevent="addGroup()">[添加分组]</a>
</div>
</div>`
})

View File

@@ -61,7 +61,7 @@
right: 0;
left: 18em;
padding-right: 2em;
padding-bottom: 1em;
padding-bottom: 2em;
overflow-y: auto;
}
.right-box.tiny {

View File

@@ -83,7 +83,7 @@
right: 0;
left: 18em;
padding-right: 2em;
padding-bottom: 1em;
padding-bottom: 2em;
overflow-y: auto;
}

View File

@@ -14,6 +14,12 @@
<p class="comment">每行一个节点IP。</p>
</td>
</tr>
<tr>
<td>所属分组</td>
<td>
<node-group-selector :v-cluster-id="clusterId"></node-group-selector>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -18,6 +18,12 @@
<node-ip-addresses-box></node-ip-addresses-box>
</td>
</tr>
<tr>
<td>所属分组</td>
<td>
<node-group-selector :v-cluster-id="clusterId"></node-group-selector>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>

View File

@@ -5,7 +5,7 @@
<input type="hidden" name="clusterId" :value="clusterId"/>
<table class="ui table definition selectable">
<tr>
<td>分组名称 *</td>
<td class="title">分组名称 *</td>
<td>
<input type="text" name="name" maxlength="50" ref="focus"/>
</td>

View File

@@ -0,0 +1,22 @@
{$layout "layout_popup"}
<h3>选择分组</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="groupId" :value="groupId"/>
<table class="ui table definition selectable">
<tr>
<td class="title">选择分组</td>
<td>
<div v-if="groups.length > 0">
<a href="" class="ui label tiny" v-for="group in groups" :class="{blue:group.id == groupId}" style="margin-bottom:0.5em" @click.prevent="selectGroup(group)">{{group.name}}</a>
<p class="comment">点击可已选中要使用的分组。</p>
</div>
<div v-else>
<p class="comment">暂时还没有可以使用的分组。</p>
</div>
</td>
</tr>
</table>
<submit-btn>确定</submit-btn>
</form>

View File

@@ -0,0 +1,8 @@
Tea.context(function () {
this.success = NotifyPopup
this.groupId = 0
this.selectGroup = function (group) {
this.groupId = group.id
}
})

View File

@@ -5,7 +5,7 @@
<input type="hidden" name="groupId" :value="group.id"/>
<table class="ui table definition selectable">
<tr>
<td>分组名称 *</td>
<td class="title">分组名称 *</td>
<td>
<input type="text" name="name" maxlength="50" ref="focus" v-model="group.name"/>
</td>

View File

@@ -5,6 +5,15 @@
<form class="ui form segment" action="/clusters/cluster">
<input type="hidden" name="clusterId" :value="clusterId"/>
<div class="ui fields inline">
<div class="ui field" v-if="groups.length > 0">
所属分组:
</div>
<div class="ui field" v-if="groups.length > 0">
<select class="ui dropdown" name="groupId" v-model="groupId">
<option value="0">[全部]</option>
<option v-for="group in groups" :value="group.id">{{group.name}}</option>
</select>
</div>
<div class="ui field">
安装状态:
</div>
@@ -41,8 +50,8 @@
<tr>
<th class="one wide">ID</th>
<th>节点名称</th>
<th>主机名</th>
<th>IP</th>
<th class="two wide">所属分组</th>
<th class="three wide">IP</th>
<th class="two wide">CPU</th>
<th class="two wide">内存</th>
<!--<th>流量</th>
@@ -52,14 +61,14 @@
</tr>
</thead>
<tr v-for="node in nodes">
<td>{{node.id}}</td>
<td nowrap="">{{node.id}}</td>
<td>{{node.name}}</td>
<td>
<span v-if="node.status.hostname != null && node.status.hostname.length > 0">{{node.status.hostname}}</span>
<span v-else>-</span>
<span v-if="node.group != null" class="ui label tiny">{{node.group.name}}</span>
<span v-else class="disabled">-</span>
</td>
<td>
<span v-if="node.ipAddresses.length == 0">-</span>
<span v-if="node.ipAddresses.length == 0" class="disabled">-</span>
<div v-else class="address-box">
<div v-for="addr in node.ipAddresses" style="margin-bottom:0.3em">
<div class="ui label tiny">{{addr.ip}}
@@ -71,11 +80,11 @@
</td>
<td>
<span v-if="node.status.isActive" :class="{red:node.status.cpuUsage > 0.80}">{{node.status.cpuUsageText}}</span>
<span v-else>-</span>
<span v-else class="disabled">-</span>
</td>
<td>
<span v-if="node.status.isActive" :class="{red:node.status.memUsage > 0.80}">{{node.status.memUsageText}}</span>
<span v-else>-</span>
<span v-else class="disabled">-</span>
</td>
<td>
<div v-if="!node.isOn">

View File

@@ -30,7 +30,14 @@
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator>SSH等更多选项</more-options-indicator></td>
<td>所属分组</td>
<td>
<span v-if="node.group != null" class="ui label tiny">{{node.group.name}}</span>
<span v-else class="disabled">没有设置分组。</span>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator>更多选项</more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>

View File

@@ -28,8 +28,15 @@
</td>
</tr>
<tr>
<td colspan="2"><strong>SSH登录信息</strong></td>
<td>所属分组</td>
<td>
<node-group-selector :v-cluster-id="clusterId" :v-group="node.group"></node-group-selector>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>SSH主机地址</td>
<td>
@@ -50,10 +57,6 @@
<grant-selector :v-grant="grant"></grant-selector>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>CPU线程数</td>
<td>