mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-07 15:20:25 +08:00
实现健康检查配置、立即执行健康检查
This commit is contained in:
@@ -76,6 +76,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"id": addr.Id,
|
"id": addr.Id,
|
||||||
"name": addr.Name,
|
"name": addr.Name,
|
||||||
"ip": addr.Ip,
|
"ip": addr.Ip,
|
||||||
|
"canAccess": addr.CanAccess,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ func (this *NodeAction) RunGet(params struct {
|
|||||||
"id": addr.Id,
|
"id": addr.Id,
|
||||||
"name": addr.Name,
|
"name": addr.Name,
|
||||||
"ip": addr.Ip,
|
"ip": addr.Ip,
|
||||||
|
"canAccess": addr.CanAccess,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/grants/grantutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/grants/grantutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/ipAddresses/ipaddressutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -54,6 +55,7 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
"id": addr.Id,
|
"id": addr.Id,
|
||||||
"name": addr.Name,
|
"name": addr.Name,
|
||||||
"ip": addr.Ip,
|
"ip": addr.Ip,
|
||||||
|
"canAccess": addr.CanAccess,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +133,7 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
LoginId int64
|
LoginId int64
|
||||||
NodeId int64
|
NodeId int64
|
||||||
Name string
|
Name string
|
||||||
IPAddresses string `alias:"ipAddresses"`
|
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
GrantId int64
|
GrantId int64
|
||||||
SshHost string
|
SshHost string
|
||||||
@@ -188,23 +190,11 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 添加新的IP地址
|
// 添加新的IP地址
|
||||||
ipAddresses := []maps.Map{}
|
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, params.IPAddressesJSON)
|
||||||
err = json.Unmarshal([]byte(params.IPAddresses), &ipAddresses)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, address := range ipAddresses {
|
|
||||||
addressId := address.GetInt64("id")
|
|
||||||
_, err = this.RPC().NodeIPAddressRPC().UpdateNodeIPAddressNodeId(this.AdminContext(), &pb.UpdateNodeIPAddressNodeIdRequest{
|
|
||||||
AddressId: addressId,
|
|
||||||
NodeId: params.NodeId,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package settings
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HealthAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HealthAction) Init() {
|
||||||
|
this.Nav("", "setting", "")
|
||||||
|
this.SecondMenu("health")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HealthAction) RunGet(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
}) {
|
||||||
|
configResp, err := this.RPC().NodeClusterRPC().FindNodeClusterHealthCheckConfig(this.AdminContext(), &pb.FindNodeClusterHealthCheckConfigRequest{ClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var config *serverconfigs.HealthCheckConfig = nil
|
||||||
|
if len(configResp.HealthCheckConfig) > 0 {
|
||||||
|
config = &serverconfigs.HealthCheckConfig{}
|
||||||
|
err = json.Unmarshal(configResp.HealthCheckConfig, config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["healthCheckConfig"] = config
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HealthAction) RunPost(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
HealthCheckJSON []byte
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
config := &serverconfigs.HealthCheckConfig{}
|
||||||
|
err := json.Unmarshal(params.HealthCheckJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().NodeClusterRPC().UpdateNodeClusterHealthCheck(this.AdminContext(), &pb.UpdateNodeClusterHealthCheckRequest{
|
||||||
|
ClusterId: params.ClusterId,
|
||||||
|
HealthCheckJSON: params.HealthCheckJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package settings
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HealthRunAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HealthRunAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HealthRunAction) RunGet(params struct{}) {
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HealthRunAction) RunPost(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
resp, err := this.RPC().NodeClusterRPC().ExecuteNodeClusterHealthCheck(this.AdminContext(), &pb.ExecuteNodeClusterHealthCheckRequest{ClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["results"] = resp.Results
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@ func init() {
|
|||||||
Helper(clusters.NewClusterHelper()).
|
Helper(clusters.NewClusterHelper()).
|
||||||
Prefix("/clusters/cluster/settings").
|
Prefix("/clusters/cluster/settings").
|
||||||
GetPost("", new(IndexAction)).
|
GetPost("", new(IndexAction)).
|
||||||
|
GetPost("/health", new(HealthAction)).
|
||||||
|
GetPost("/healthRun", new(HealthRunAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,5 +84,10 @@ func (this *ClusterHelper) createSettingMenu(clusterId string, selectedItem stri
|
|||||||
"url": "/clusters/cluster/settings?clusterId=" + clusterId,
|
"url": "/clusters/cluster/settings?clusterId=" + clusterId,
|
||||||
"isActive": selectedItem == "basic",
|
"isActive": selectedItem == "basic",
|
||||||
})
|
})
|
||||||
|
items = append(items, maps.Map{
|
||||||
|
"name": "健康检查",
|
||||||
|
"url": "/clusters/cluster/settings/health?clusterId=" + clusterId,
|
||||||
|
"isActive": selectedItem == "health",
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package ipAddresses
|
package ipAddresses
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreatePopupAction struct {
|
type CreatePopupAction struct {
|
||||||
@@ -21,30 +21,27 @@ func (this *CreatePopupAction) RunGet(params struct{}) {
|
|||||||
|
|
||||||
func (this *CreatePopupAction) RunPost(params struct {
|
func (this *CreatePopupAction) RunPost(params struct {
|
||||||
IP string `alias:"ip"`
|
IP string `alias:"ip"`
|
||||||
|
CanAccess bool
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
}) {
|
}) {
|
||||||
// TODO 严格校验IP地址
|
// TODO 严格校验IP地址
|
||||||
|
|
||||||
|
ip := net.ParseIP(params.IP)
|
||||||
|
if len(ip) == 0 {
|
||||||
|
this.Fail("请输入正确的IP")
|
||||||
|
}
|
||||||
|
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("ip", params.IP).
|
Field("ip", params.IP).
|
||||||
Require("请输入IP地址")
|
Require("请输入IP地址")
|
||||||
|
|
||||||
resp, err := this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
|
|
||||||
NodeId: 0,
|
|
||||||
Name: params.Name,
|
|
||||||
Ip: params.IP,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["ipAddress"] = maps.Map{
|
this.Data["ipAddress"] = maps.Map{
|
||||||
"name": params.Name,
|
"name": params.Name,
|
||||||
|
"canAccess": params.CanAccess,
|
||||||
"ip": params.IP,
|
"ip": params.IP,
|
||||||
"id": resp.AddressId,
|
"id": 0,
|
||||||
}
|
}
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package ipaddressutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 保存一组IP地址
|
||||||
|
func UpdateNodeIPAddresses(parentAction *actionutils.ParentAction, nodeId int64, ipAddressesJSON []byte) error {
|
||||||
|
addresses := []maps.Map{}
|
||||||
|
err := json.Unmarshal(ipAddressesJSON, &addresses)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, addr := range addresses {
|
||||||
|
addrId := addr.GetInt64("id")
|
||||||
|
if addrId > 0 {
|
||||||
|
_, err = parentAction.RPC().NodeIPAddressRPC().UpdateNodeIPAddress(parentAction.AdminContext(), &pb.UpdateNodeIPAddressRequest{
|
||||||
|
AddressId: addrId,
|
||||||
|
Ip: addr.GetString("ip"),
|
||||||
|
Name: addr.GetString("name"),
|
||||||
|
CanAccess: addr.GetBool("canAccess"),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, err = parentAction.RPC().NodeIPAddressRPC().CreateNodeIPAddress(parentAction.AdminContext(), &pb.CreateNodeIPAddressRequest{
|
||||||
|
NodeId: nodeId,
|
||||||
|
Name: addr.GetString("name"),
|
||||||
|
Ip: addr.GetString("ip"),
|
||||||
|
CanAccess: addr.GetBool("canAccess"),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package ipAddresses
|
package ipAddresses
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UpdatePopupAction struct {
|
type UpdatePopupAction struct {
|
||||||
@@ -18,23 +18,6 @@ func (this *UpdatePopupAction) Init() {
|
|||||||
func (this *UpdatePopupAction) RunGet(params struct {
|
func (this *UpdatePopupAction) RunGet(params struct {
|
||||||
AddressId int64
|
AddressId int64
|
||||||
}) {
|
}) {
|
||||||
addressResp, err := this.RPC().NodeIPAddressRPC().FindEnabledNodeIPAddress(this.AdminContext(), &pb.FindEnabledNodeIPAddressRequest{AddressId: params.AddressId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
address := addressResp.IpAddress
|
|
||||||
if address == nil {
|
|
||||||
this.WriteString("找不到要修改的IP地址")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["address"] = maps.Map{
|
|
||||||
"id": address.Id,
|
|
||||||
"name": address.Name,
|
|
||||||
"ip": address.Ip,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +25,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
AddressId int64
|
AddressId int64
|
||||||
IP string `alias:"ip"`
|
IP string `alias:"ip"`
|
||||||
Name string
|
Name string
|
||||||
|
CanAccess bool
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
}) {
|
}) {
|
||||||
@@ -51,20 +35,16 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
Field("ip", params.IP).
|
Field("ip", params.IP).
|
||||||
Require("请输入IP地址")
|
Require("请输入IP地址")
|
||||||
|
|
||||||
_, err := this.RPC().NodeIPAddressRPC().UpdateNodeIPAddress(this.AdminContext(), &pb.UpdateNodeIPAddressRequest{
|
ip := net.ParseIP(params.IP)
|
||||||
AddressId: params.AddressId,
|
if len(ip) == 0 {
|
||||||
Name: params.Name,
|
this.Fail("请输入正确的IP")
|
||||||
Ip: params.IP,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Data["ipAddress"] = maps.Map{
|
this.Data["ipAddress"] = maps.Map{
|
||||||
"name": params.Name,
|
"name": params.Name,
|
||||||
"ip": params.IP,
|
"ip": params.IP,
|
||||||
"id": params.AddressId,
|
"id": params.AddressId,
|
||||||
|
"canAccess": params.CanAccess,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
|
|||||||
168
web/public/js/components/common/health-check-config-box.js
Normal file
168
web/public/js/components/common/health-check-config-box.js
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
Vue.component("health-check-config-box", {
|
||||||
|
props: ["v-health-check-config"],
|
||||||
|
data: function () {
|
||||||
|
let healthCheckConfig = this.vHealthCheckConfig
|
||||||
|
let urlProtocol = "http"
|
||||||
|
let urlPort = ""
|
||||||
|
let urlRequestURI = "/"
|
||||||
|
|
||||||
|
if (healthCheckConfig == null) {
|
||||||
|
healthCheckConfig = {
|
||||||
|
isOn: false,
|
||||||
|
url: "",
|
||||||
|
interval: {count: 60, unit: "second"},
|
||||||
|
statusCodes: [200],
|
||||||
|
timeout: {count: 10, unit: "second"},
|
||||||
|
countTries: 3,
|
||||||
|
tryDelay: {count: 100, unit: "ms"}
|
||||||
|
}
|
||||||
|
let that = this
|
||||||
|
setTimeout(function () {
|
||||||
|
that.changeURL()
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
let url = new URL(healthCheckConfig.url)
|
||||||
|
urlProtocol = url.protocol.substring(0, url.protocol.length - 1)
|
||||||
|
urlPort = url.port
|
||||||
|
urlRequestURI = url.pathname
|
||||||
|
if (url.search.length > 0) {
|
||||||
|
urlRequestURI += url.search
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
healthCheck: healthCheckConfig,
|
||||||
|
advancedVisible: false,
|
||||||
|
urlProtocol: urlProtocol,
|
||||||
|
urlPort: urlPort,
|
||||||
|
urlRequestURI: urlRequestURI
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
urlRequestURI: function () {
|
||||||
|
if (this.urlRequestURI.length > 0 && this.urlRequestURI[0] != "/") {
|
||||||
|
this.urlRequestURI = "/" + this.urlRequestURI
|
||||||
|
}
|
||||||
|
this.changeURL()
|
||||||
|
},
|
||||||
|
urlPort: function (v) {
|
||||||
|
let port = parseInt(v)
|
||||||
|
if (!isNaN(port)) {
|
||||||
|
this.urlPort = port.toString()
|
||||||
|
} else {
|
||||||
|
this.urlPort = ""
|
||||||
|
}
|
||||||
|
this.changeURL()
|
||||||
|
},
|
||||||
|
urlProtocol: function () {
|
||||||
|
this.changeURL()
|
||||||
|
},
|
||||||
|
"healthCheck.countTries": function (v) {
|
||||||
|
let count = parseInt(v)
|
||||||
|
if (!isNaN(count)) {
|
||||||
|
this.healthCheck.countTries = count
|
||||||
|
} else {
|
||||||
|
this.healthCheck.countTries = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showAdvanced: function () {
|
||||||
|
this.advancedVisible = !this.advancedVisible
|
||||||
|
},
|
||||||
|
changeURL: function () {
|
||||||
|
this.healthCheck.url = this.urlProtocol + "://${host}" + ((this.urlPort.length > 0) ? ":" + this.urlPort : "") + this.urlRequestURI
|
||||||
|
},
|
||||||
|
changeStatus: function (values) {
|
||||||
|
this.healthCheck.statusCodes = values.$map(function (k, v) {
|
||||||
|
let status = parseInt(v)
|
||||||
|
if (isNaN(status)) {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log(this.healthCheck.statusCodes)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<input type="hidden" name="healthCheckJSON" :value="JSON.stringify(healthCheck)"/>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="title">是否启用</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" value="1" v-model="healthCheck.isOn"/>
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tbody v-show="healthCheck.isOn">
|
||||||
|
<tr>
|
||||||
|
<td>URL *</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui fields inline">
|
||||||
|
<div class="ui field">
|
||||||
|
<select class="ui dropdown" v-model="urlProtocol">
|
||||||
|
<option value="http">http://</option>
|
||||||
|
<option value="https">https://</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="ui field">
|
||||||
|
<var style="color:grey">\${host}</var>
|
||||||
|
</div>
|
||||||
|
<div class="ui field">:</div>
|
||||||
|
<div class="ui field">
|
||||||
|
<input type="text" maxlength="5" style="width:5.4em" placeholder="端口" v-model="urlPort"/>
|
||||||
|
</div>
|
||||||
|
<div class="ui field">
|
||||||
|
<input type="text" v-model="urlRequestURI" placeholder="/" style="width:23em"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<p class="comment" v-if="healthCheck.url.length > 0">拼接后的URL:<code-label>{{healthCheck.url}}</code-label>,其中\${host}指的是节点地址。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>检测时间间隔</td>
|
||||||
|
<td>
|
||||||
|
<time-duration-box :v-value="healthCheck.interval"></time-duration-box>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tbody v-show="healthCheck.isOn">
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><more-options-angle @change="showAdvanced"></more-options-angle></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tbody v-show="advancedVisible && healthCheck.isOn">
|
||||||
|
<tr>
|
||||||
|
<td>允许的状态码</td>
|
||||||
|
<td>
|
||||||
|
<values-box :values="healthCheck.statusCodes" maxlength="3" @change="changeStatus"></values-box>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>超时时间</td>
|
||||||
|
<td>
|
||||||
|
<time-duration-box :v-value="healthCheck.timeout"></time-duration-box>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>连续尝试次数</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" v-model="healthCheck.countTries" style="width: 5em" maxlength="2"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>每次尝试间隔</td>
|
||||||
|
<td>
|
||||||
|
<time-duration-box :v-value="healthCheck.tryDelay"></time-duration-box>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="margin"></div>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -37,10 +37,12 @@ Vue.component("values-box", {
|
|||||||
} else {
|
} else {
|
||||||
this.vValues.push(this.value);
|
this.vValues.push(this.value);
|
||||||
}
|
}
|
||||||
this.cancel();
|
this.cancel()
|
||||||
|
this.$emit("change", this.vValues)
|
||||||
},
|
},
|
||||||
remove: function (index) {
|
remove: function (index) {
|
||||||
this.vValues.$remove(index);
|
this.vValues.$remove(index)
|
||||||
|
this.$emit("change", this.vValues)
|
||||||
},
|
},
|
||||||
cancel: function () {
|
cancel: function () {
|
||||||
this.isUpdating = false;
|
this.isUpdating = false;
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ Vue.component("node-ip-addresses-box", {
|
|||||||
methods: {
|
methods: {
|
||||||
// 添加IP地址
|
// 添加IP地址
|
||||||
addIPAddress: function () {
|
addIPAddress: function () {
|
||||||
|
window.UPDATING_NODE_IP_ADDRESS = null
|
||||||
|
|
||||||
let that = this;
|
let that = this;
|
||||||
teaweb.popup("/nodes/ipAddresses/createPopup", {
|
teaweb.popup("/nodes/ipAddresses/createPopup", {
|
||||||
callback: function (resp) {
|
callback: function (resp) {
|
||||||
@@ -18,8 +20,10 @@ Vue.component("node-ip-addresses-box", {
|
|||||||
|
|
||||||
// 修改地址
|
// 修改地址
|
||||||
updateIPAddress: function (index, address) {
|
updateIPAddress: function (index, address) {
|
||||||
|
window.UPDATING_NODE_IP_ADDRESS = address
|
||||||
|
|
||||||
let that = this;
|
let that = this;
|
||||||
teaweb.popup("/nodes/ipAddresses/updatePopup?addressId=" + address.id, {
|
teaweb.popup("/nodes/ipAddresses/updatePopup", {
|
||||||
callback: function (resp) {
|
callback: function (resp) {
|
||||||
Vue.set(that.ipAddresses, index, resp.data.ipAddress);
|
Vue.set(that.ipAddresses, index, resp.data.ipAddress);
|
||||||
}
|
}
|
||||||
@@ -32,11 +36,13 @@ Vue.component("node-ip-addresses-box", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `<div>
|
template: `<div>
|
||||||
<input type="hidden" name="ipAddresses" :value="JSON.stringify(ipAddresses)"/>
|
<input type="hidden" name="ipAddressesJSON" :value="JSON.stringify(ipAddresses)"/>
|
||||||
<div v-if="ipAddresses.length > 0">
|
<div v-if="ipAddresses.length > 0">
|
||||||
<div>
|
<div>
|
||||||
<div v-for="(address, index) in ipAddresses" class="ui label small">
|
<div v-for="(address, index) in ipAddresses" class="ui label small">
|
||||||
{{address.ip}}<span class="small" v-if="address.name.length > 0">({{address.name}})</span>
|
{{address.ip}}
|
||||||
|
<span class="small" v-if="address.name.length > 0">({{address.name}}<span v-if="!address.canAccess">,不可访问</span>)</span>
|
||||||
|
<span class="small" v-if="address.name.length == 0 && !address.canAccess">(不可访问)</span>
|
||||||
<a href="" title="修改" @click.prevent="updateIPAddress(index, address)"><i class="icon pencil small"></i></a>
|
<a href="" title="修改" @click.prevent="updateIPAddress(index, address)"><i class="icon pencil small"></i></a>
|
||||||
<a href="" title="删除" @click.prevent="removeIPAddress(index)"><i class="icon remove"></i></a>
|
<a href="" title="删除" @click.prevent="removeIPAddress(index)"><i class="icon remove"></i></a>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,6 +52,5 @@ Vue.component("node-ip-addresses-box", {
|
|||||||
<div>
|
<div>
|
||||||
<button class="ui button small" type="button" @click.prevent="addIPAddress()">+</button>
|
<button class="ui button small" type="button" @click.prevent="addIPAddress()">+</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="comment">添加已经绑定的IP地址,仅做记录用。</p>
|
|
||||||
</div>`
|
</div>`
|
||||||
})
|
})
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "/left_menu"}
|
|
||||||
|
|
||||||
<div class="right-box">
|
|
||||||
{$template "menu"}
|
{$template "menu"}
|
||||||
|
|
||||||
<form class="ui form segment" action="/clusters/cluster">
|
<form class="ui form segment" action="/clusters/cluster">
|
||||||
@@ -61,7 +59,10 @@
|
|||||||
<span v-if="node.ipAddresses.length == 0">-</span>
|
<span v-if="node.ipAddresses.length == 0">-</span>
|
||||||
<div v-else class="address-box">
|
<div v-else class="address-box">
|
||||||
<div v-for="addr in node.ipAddresses" style="margin-bottom:0.3em">
|
<div v-for="addr in node.ipAddresses" style="margin-bottom:0.3em">
|
||||||
<div class="ui label tiny">{{addr.ip}} <span class="small">({{addr.name}})</span></div>
|
<div class="ui label tiny">{{addr.ip}}
|
||||||
|
<span class="small" v-if="addr.name.length > 0">({{addr.name}}<span v-if="!addr.canAccess">,不可访问</span>)</span>
|
||||||
|
<span class="small" v-if="addr.name.length == 0 && !addr.canAccess">(不可访问)</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -99,4 +100,3 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="page" v-html="page"></div>
|
<div class="page" v-html="page"></div>
|
||||||
</div>
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "/left_menu"}
|
|
||||||
|
|
||||||
<div class="right-box">
|
|
||||||
{$template "menu"}
|
{$template "menu"}
|
||||||
<p>可以通过节点安装包中的<code-label>configs/cluster.yaml</code-label>直接自动注册节点。</p>
|
<p>可以通过节点安装包中的<code-label>configs/cluster.yaml</code-label>直接自动注册节点。</p>
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
@@ -17,4 +15,3 @@ secret: "{{cluster.secret}}"</pre>
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
<second-menu>
|
<second-menu>
|
||||||
|
<menu-item :href="'/clusters/cluster?clusterId=' + clusterId">节点列表</menu-item>
|
||||||
|
<span class="item">|</span>
|
||||||
<menu-item :href="'/clusters/cluster/node?clusterId=' + clusterId + '&nodeId=' + nodeId" code="node">节点详情</menu-item>
|
<menu-item :href="'/clusters/cluster/node?clusterId=' + clusterId + '&nodeId=' + nodeId" code="node">节点详情</menu-item>
|
||||||
<menu-item :href="'/clusters/cluster/node/logs?clusterId=' + clusterId + '&nodeId=' + nodeId" code="log">运行日志</menu-item>
|
<menu-item :href="'/clusters/cluster/node/logs?clusterId=' + clusterId + '&nodeId=' + nodeId" code="log">运行日志</menu-item>
|
||||||
<menu-item :href="'/clusters/cluster/node/update?clusterId=' + clusterId + '&nodeId=' + nodeId" code="update">修改设置</menu-item>
|
<menu-item :href="'/clusters/cluster/node/update?clusterId=' + clusterId + '&nodeId=' + nodeId" code="update">修改设置</menu-item>
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "/left_menu"}
|
|
||||||
|
|
||||||
<div class="right-box">
|
|
||||||
{$template "/clusters/cluster/menu"}
|
{$template "/clusters/cluster/menu"}
|
||||||
|
|
||||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
@@ -42,4 +40,3 @@
|
|||||||
</table>
|
</table>
|
||||||
<submit-btn></submit-btn>
|
<submit-btn></submit-btn>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "/left_menu"}
|
|
||||||
|
|
||||||
<div class="right-box">
|
|
||||||
{$template "node_menu"}
|
{$template "node_menu"}
|
||||||
|
|
||||||
<!-- 已安装 -->
|
<!-- 已安装 -->
|
||||||
@@ -54,4 +52,3 @@ secret: "{{node.secret}}"</pre>
|
|||||||
|
|
||||||
<a href="" @click.prevent="updateNodeIsInstalled(true)">[修改为已安装状态]</a>
|
<a href="" @click.prevent="updateNodeIsInstalled(true)">[修改为已安装状态]</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "/left_menu"}
|
|
||||||
|
|
||||||
<div class="right-box">
|
|
||||||
{$template "node_menu"}
|
{$template "node_menu"}
|
||||||
|
|
||||||
<p class="comment" v-if="logs.length == 0">暂时还没有日志。</p>
|
<p class="comment" v-if="logs.length == 0">暂时还没有日志。</p>
|
||||||
@@ -20,4 +18,3 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="page" v-html="page"></div>
|
<div class="page" v-html="page"></div>
|
||||||
</div>
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "/left_menu"}
|
|
||||||
|
|
||||||
<div class="right-box">
|
|
||||||
{$template "node_menu"}
|
{$template "node_menu"}
|
||||||
|
|
||||||
<h3>节点详情</h3>
|
<h3>节点详情</h3>
|
||||||
@@ -19,8 +17,10 @@
|
|||||||
<td>
|
<td>
|
||||||
<div v-if="node.ipAddresses.length > 0">
|
<div v-if="node.ipAddresses.length > 0">
|
||||||
<div>
|
<div>
|
||||||
<div v-for="(address, index) in node.ipAddresses" class="ui label small">
|
<div v-for="(address, index) in node.ipAddresses" class="ui label tiny">
|
||||||
{{address.ip}}<span class="small">({{address.name}})</span>
|
{{address.ip}}
|
||||||
|
<span class="small" v-if="address.name.length > 0">({{address.name}}<span v-if="!address.canAccess">,不可访问</span>)</span>
|
||||||
|
<span class="small" v-if="address.name.length == 0 && !address.canAccess">(不可访问)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,4 +98,3 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "/left_menu"}
|
|
||||||
|
|
||||||
<div class="right-box">
|
|
||||||
{$template "node_menu"}
|
{$template "node_menu"}
|
||||||
|
|
||||||
<h3>修改节点</h3>
|
<h3>修改节点</h3>
|
||||||
@@ -77,4 +75,3 @@
|
|||||||
</table>
|
</table>
|
||||||
<submit-btn></submit-btn>
|
<submit-btn></submit-btn>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
10
web/views/@default/clusters/cluster/settings/health.html
Normal file
10
web/views/@default/clusters/cluster/settings/health.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "/left_menu"}
|
||||||
|
|
||||||
|
<div class="right-box">
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<input type="hidden" name="clusterId" :value="clusterId"/>
|
||||||
|
<health-check-config-box :v-health-check-config="healthCheckConfig"></health-check-config-box>
|
||||||
|
<submit-btn></submit-btn> <a href="" @click.prevent="run()">立即检查</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
11
web/views/@default/clusters/cluster/settings/health.js
Normal file
11
web/views/@default/clusters/cluster/settings/health.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.success = NotifyReloadSuccess("保存成功")
|
||||||
|
|
||||||
|
this.run = function () {
|
||||||
|
teaweb.confirm("确定要对当前集群下的所有节点进行健康检查吗?", function () {
|
||||||
|
teaweb.popup("/clusters/cluster/settings/healthRun?clusterId=" + this.clusterId, {
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
27
web/views/@default/clusters/cluster/settings/healthRun.html
Normal file
27
web/views/@default/clusters/cluster/settings/healthRun.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3>健康检查</h3>
|
||||||
|
|
||||||
|
<span class="red" v-if="isRequesting">正在执行中,请等待执行完毕...</span>
|
||||||
|
|
||||||
|
<form class="ui form" v-if="!isRequesting">
|
||||||
|
<p>成功节点:<span class="green">{{countSuccess}}</span> 失败节点:<span class="red">{{countFail}}</span></p>
|
||||||
|
<table class="ui table selectable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>节点</th>
|
||||||
|
<th>结果</th>
|
||||||
|
<th>耗时</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr v-for="result in results">
|
||||||
|
<td>{{result.node.name}}<span class="small" v-if="result.nodeAddr != null && result.nodeAddr.length > 0">({{result.nodeAddr}})</span></td>
|
||||||
|
<td>
|
||||||
|
<span v-if="!result.isOk" class="red">失败:{{result.error}}</span>
|
||||||
|
<span v-else class="green">成功</span>
|
||||||
|
</td>
|
||||||
|
<td>{{result.costMs}}ms</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button class="ui button primary" type="button" @click.prevent="success">完成</button>
|
||||||
|
</form>
|
||||||
39
web/views/@default/clusters/cluster/settings/healthRun.js
Normal file
39
web/views/@default/clusters/cluster/settings/healthRun.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.success = NotifyPopup
|
||||||
|
|
||||||
|
this.isRequesting = false
|
||||||
|
this.results = []
|
||||||
|
this.countSuccess = 0
|
||||||
|
this.countFail = 0
|
||||||
|
|
||||||
|
this.$delay(function () {
|
||||||
|
this.run()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.run = function () {
|
||||||
|
this.isRequesting = true
|
||||||
|
|
||||||
|
this.$post("$")
|
||||||
|
.params({
|
||||||
|
clusterId: this.clusterId
|
||||||
|
})
|
||||||
|
.success(function (resp) {
|
||||||
|
this.results = resp.data.results
|
||||||
|
let that = this
|
||||||
|
this.results.forEach(function (v) {
|
||||||
|
v.costMs = Math.ceil(v.costMs)
|
||||||
|
if (isNaN(v.costMs)) {
|
||||||
|
v.costMs = 0
|
||||||
|
}
|
||||||
|
if (v.isOk) {
|
||||||
|
that.countSuccess++
|
||||||
|
} else {
|
||||||
|
that.countFail++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.done(function () {
|
||||||
|
this.isRequesting = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -10,6 +10,16 @@
|
|||||||
<input type="text" name="ip" maxlength="128" ref="focus"/>
|
<input type="text" name="ip" maxlength="128" ref="focus"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否可以访问</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" name="canAccess" value="1" checked="checked"/>
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
<p class="comment">是否为可以公开访问的IP。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">备注</td>
|
<td class="title">备注</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -11,6 +11,16 @@
|
|||||||
<input type="text" name="ip" maxlength="128" ref="focus" v-model="address.ip"/>
|
<input type="text" name="ip" maxlength="128" ref="focus" v-model="address.ip"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>是否可以访问</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" name="canAccess" value="1" v-model="address.canAccess"/>
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
<p class="comment">是否为可以公开访问的IP。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">备注</td>
|
<td class="title">备注</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
this.success = NotifyPopup;
|
this.success = NotifyPopup;
|
||||||
|
|
||||||
|
this.address = window.parent.UPDATING_NODE_IP_ADDRESS
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user