diff --git a/README.md b/README.md
index a8918f7..615ff95 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# 哪吒面板
-![dashboard](https://img.shields.io/badge/管理面板-v0.3.8-brightgreen?style=for-the-badge&logo=github) ![Agent release](https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&label=Agent&style=for-the-badge&logo=github)
+![dashboard](https://img.shields.io/badge/管理面板-v0.3.9-brightgreen?style=for-the-badge&logo=github) ![Agent release](https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&label=Agent&style=for-the-badge&logo=github)
系统状态监控报警、API(SSL证书变更、即将到期、到期)/TCP端口存活/PING 监控、计划任务(可以定时在Agent上执行命令,备份、重启、What ever you want)、极省资源,64M 服务器也能装 agent。
diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go
index 16d9b1f..40de3cd 100644
--- a/cmd/dashboard/controller/member_api.go
+++ b/cmd/dashboard/controller/member_api.go
@@ -15,7 +15,6 @@ import (
"github.com/naiba/nezha/pkg/mygin"
"github.com/naiba/nezha/pkg/utils"
pb "github.com/naiba/nezha/proto"
- "github.com/naiba/nezha/service/alertmanager"
"github.com/naiba/nezha/service/dao"
)
@@ -37,6 +36,7 @@ func (ma *memberAPI) serve() {
mr.POST("/server", ma.addOrEditServer)
mr.POST("/monitor", ma.addOrEditMonitor)
mr.POST("/cron", ma.addOrEditCron)
+ mr.GET("/cron/:id/manual", ma.manualTrigger)
mr.POST("/notification", ma.addOrEditNotification)
mr.POST("/alert-rule", ma.addOrEditAlertRule)
mr.POST("/setting", ma.updateSetting)
@@ -67,7 +67,7 @@ func (ma *memberAPI) delete(c *gin.Context) {
case "notification":
err = dao.DB.Delete(&model.Notification{}, "id = ?", id).Error
if err == nil {
- alertmanager.OnDeleteNotification(id)
+ dao.OnDeleteNotification(id)
}
case "monitor":
err = dao.DB.Delete(&model.Monitor{}, "id = ?", id).Error
@@ -88,7 +88,7 @@ func (ma *memberAPI) delete(c *gin.Context) {
case "alert-rule":
err = dao.DB.Delete(&model.AlertRule{}, "id = ?", id).Error
if err == nil {
- alertmanager.OnDeleteAlert(id)
+ dao.OnDeleteAlert(id)
}
}
if err != nil {
@@ -281,7 +281,7 @@ func (ma *memberAPI) addOrEditCron(c *gin.Context) {
Type: model.TaskTypeCommand,
})
} else {
- alertmanager.SendNotification(fmt.Sprintf("计划任务:%s,服务器:%d 离线,无法执行。", cr.Name, cr.Servers[j]), false)
+ dao.SendNotification(fmt.Sprintf("计划任务:%s,服务器:%d 离线,无法执行。", cr.Name, cr.Servers[j]), false)
}
}
})
@@ -294,6 +294,23 @@ func (ma *memberAPI) addOrEditCron(c *gin.Context) {
})
}
+func (ma *memberAPI) manualTrigger(c *gin.Context) {
+ var cr model.Cron
+ if err := dao.DB.First(&cr, "id = ?", c.Param("id")).Error; err != nil {
+ c.JSON(http.StatusOK, model.Response{
+ Code: http.StatusBadRequest,
+ Message: err.Error(),
+ })
+ return
+ }
+
+ dao.CronTrigger(&cr)
+
+ c.JSON(http.StatusOK, model.Response{
+ Code: http.StatusOK,
+ })
+}
+
type notificationForm struct {
ID uint64
Name string
@@ -333,7 +350,7 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) {
})
return
}
- alertmanager.OnRefreshOrAddNotification(n)
+ dao.OnRefreshOrAddNotification(n)
c.JSON(http.StatusOK, model.Response{
Code: http.StatusOK,
})
@@ -384,7 +401,7 @@ func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
})
return
}
- alertmanager.OnRefreshOrAddAlert(r)
+ dao.OnRefreshOrAddAlert(r)
c.JSON(http.StatusOK, model.Response{
Code: http.StatusOK,
})
diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go
index fe9dce4..e34ce1c 100644
--- a/cmd/dashboard/main.go
+++ b/cmd/dashboard/main.go
@@ -13,7 +13,6 @@ import (
"github.com/naiba/nezha/cmd/dashboard/rpc"
"github.com/naiba/nezha/model"
pb "github.com/naiba/nezha/proto"
- "github.com/naiba/nezha/service/alertmanager"
"github.com/naiba/nezha/service/dao"
)
@@ -90,7 +89,7 @@ func loadCrons() {
Type: model.TaskTypeCommand,
})
} else {
- alertmanager.SendNotification(fmt.Sprintf("计划任务:%s,服务器:%d 离线,无法执行。", cr.Name, cr.Servers[j]), false)
+ dao.SendNotification(fmt.Sprintf("计划任务:%s,服务器:%d 离线,无法执行。", cr.Name, cr.Servers[j]), false)
}
}
})
@@ -106,5 +105,5 @@ func main() {
go controller.ServeWeb(dao.Conf.HTTPPort)
go rpc.ServeRPC(5555)
go rpc.DispatchTask(time.Minute * 3)
- alertmanager.Start()
+ dao.AlertSentinelStart()
}
diff --git a/resource/static/main.js b/resource/static/main.js
index eb85505..8f93b3f 100644
--- a/resource/static/main.js
+++ b/resource/static/main.js
@@ -149,7 +149,7 @@ function addOrEditCron(cron) {
modal.find('input[name=ID]').val(cron ? cron.ID : null)
modal.find('input[name=Name]').val(cron ? cron.Name : null)
modal.find('input[name=Scheduler]').val(cron ? cron.Scheduler : null)
- modal.find('a.ui.label.visible').each((i,el) => {
+ modal.find('a.ui.label.visible').each((i, el) => {
el.remove()
})
var servers
@@ -192,6 +192,42 @@ function deleteRequest(api) {
});
}
+function manualTrigger(btn, cronId) {
+ $(btn).toggleClass('loading')
+ $.ajax({
+ url: '/api/cron/' + cronId + '/manual',
+ type: 'GET',
+ }).done(resp => {
+ $(btn).toggleClass('loading')
+ if (resp.code == 200) {
+ $.suiAlert({
+ title: '触发成功,等待执行结果',
+ type: 'success',
+ description: resp.message,
+ time: '3',
+ position: 'top-center',
+ });
+ } else {
+ $.suiAlert({
+ title: '触发失败 ',
+ type: 'error',
+ description: resp.code + ':' + resp.message,
+ time: '3',
+ position: 'top-center',
+ });
+ }
+ }).fail(err => {
+ $(btn).toggleClass('loading')
+ $.suiAlert({
+ title: '触发失败 ',
+ type: 'error',
+ description: '网络错误:' + err.responseText,
+ time: '3',
+ position: 'top-center',
+ });
+ });
+}
+
function logout(id) {
$.post('/api/logout', JSON.stringify({ id: id })).done(function (resp) {
if (resp.code == 200) {
diff --git a/resource/template/common/footer.html b/resource/template/common/footer.html
index 91c8f06..3c3bbdd 100644
--- a/resource/template/common/footer.html
+++ b/resource/template/common/footer.html
@@ -8,7 +8,7 @@
-
+