mirror of
https://github.com/henrygd/beszel.git
synced 2026-04-21 04:01:50 +02:00
updates
This commit is contained in:
@@ -134,11 +134,6 @@ func (h *Hub) registerApiRoutes(se *core.ServeEvent) error {
|
||||
// get container info
|
||||
apiAuth.GET("/containers/info", h.getContainerInfo)
|
||||
}
|
||||
// network probe routes
|
||||
apiAuth.GET("/network-probes", h.listNetworkProbes)
|
||||
apiAuth.POST("/network-probes", h.createNetworkProbe).BindFunc(excludeReadOnlyRole)
|
||||
apiAuth.DELETE("/network-probes", h.deleteNetworkProbe).BindFunc(excludeReadOnlyRole)
|
||||
apiAuth.GET("/network-probe-stats", h.getNetworkProbeStats)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
package hub
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// listNetworkProbes handles GET /api/beszel/network-probes
|
||||
func (h *Hub) listNetworkProbes(e *core.RequestEvent) error {
|
||||
systemID := e.Request.URL.Query().Get("system")
|
||||
if systemID == "" {
|
||||
return e.BadRequestError("system parameter required", nil)
|
||||
}
|
||||
system, err := h.sm.GetSystem(systemID)
|
||||
if err != nil || !system.HasUser(e.App, e.Auth) {
|
||||
return e.NotFoundError("", nil)
|
||||
}
|
||||
|
||||
records, err := e.App.FindRecordsByFilter(
|
||||
"network_probes",
|
||||
"system = {:system}",
|
||||
"-created",
|
||||
0, 0,
|
||||
dbx.Params{"system": systemID},
|
||||
)
|
||||
if err != nil {
|
||||
return e.InternalServerError("", err)
|
||||
}
|
||||
|
||||
type probeRecord struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Target string `json:"target"`
|
||||
Protocol string `json:"protocol"`
|
||||
Port int `json:"port"`
|
||||
Interval int `json:"interval"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
result := make([]probeRecord, 0, len(records))
|
||||
for _, r := range records {
|
||||
result = append(result, probeRecord{
|
||||
Id: r.Id,
|
||||
Name: r.GetString("name"),
|
||||
Target: r.GetString("target"),
|
||||
Protocol: r.GetString("protocol"),
|
||||
Port: r.GetInt("port"),
|
||||
Interval: r.GetInt("interval"),
|
||||
Enabled: r.GetBool("enabled"),
|
||||
})
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// createNetworkProbe handles POST /api/beszel/network-probes
|
||||
func (h *Hub) createNetworkProbe(e *core.RequestEvent) error {
|
||||
var req struct {
|
||||
System string `json:"system"`
|
||||
Name string `json:"name"`
|
||||
Target string `json:"target"`
|
||||
Protocol string `json:"protocol"`
|
||||
Port int `json:"port"`
|
||||
Interval int `json:"interval"`
|
||||
}
|
||||
if err := json.NewDecoder(e.Request.Body).Decode(&req); err != nil {
|
||||
return e.BadRequestError("invalid request body", err)
|
||||
}
|
||||
if req.System == "" || req.Target == "" || req.Protocol == "" {
|
||||
return e.BadRequestError("system, target, and protocol are required", nil)
|
||||
}
|
||||
if req.Protocol != "icmp" && req.Protocol != "tcp" && req.Protocol != "http" {
|
||||
return e.BadRequestError("protocol must be icmp, tcp, or http", nil)
|
||||
}
|
||||
if req.Protocol == "http" && !strings.HasPrefix(req.Target, "http://") && !strings.HasPrefix(req.Target, "https://") {
|
||||
return e.BadRequestError("http probe target must start with http:// or https://", nil)
|
||||
}
|
||||
if req.Interval <= 0 {
|
||||
req.Interval = 10
|
||||
}
|
||||
|
||||
system, err := h.sm.GetSystem(req.System)
|
||||
if err != nil || !system.HasUser(e.App, e.Auth) {
|
||||
return e.NotFoundError("", nil)
|
||||
}
|
||||
|
||||
collection, err := e.App.FindCachedCollectionByNameOrId("network_probes")
|
||||
if err != nil {
|
||||
return e.InternalServerError("", err)
|
||||
}
|
||||
|
||||
record := core.NewRecord(collection)
|
||||
record.Set("system", req.System)
|
||||
record.Set("name", req.Name)
|
||||
record.Set("target", req.Target)
|
||||
record.Set("protocol", req.Protocol)
|
||||
record.Set("port", req.Port)
|
||||
record.Set("interval", req.Interval)
|
||||
record.Set("enabled", true)
|
||||
|
||||
if err := e.App.Save(record); err != nil {
|
||||
return e.InternalServerError("", err)
|
||||
}
|
||||
|
||||
// Sync probes to agent
|
||||
h.syncProbesToAgent(req.System)
|
||||
|
||||
return e.JSON(http.StatusOK, map[string]string{"id": record.Id})
|
||||
}
|
||||
|
||||
// deleteNetworkProbe handles DELETE /api/beszel/network-probes
|
||||
func (h *Hub) deleteNetworkProbe(e *core.RequestEvent) error {
|
||||
probeID := e.Request.URL.Query().Get("id")
|
||||
if probeID == "" {
|
||||
return e.BadRequestError("id parameter required", nil)
|
||||
}
|
||||
|
||||
record, err := e.App.FindRecordById("network_probes", probeID)
|
||||
if err != nil {
|
||||
return e.NotFoundError("", nil)
|
||||
}
|
||||
|
||||
systemID := record.GetString("system")
|
||||
system, err := h.sm.GetSystem(systemID)
|
||||
if err != nil || !system.HasUser(e.App, e.Auth) {
|
||||
return e.NotFoundError("", nil)
|
||||
}
|
||||
|
||||
if err := e.App.Delete(record); err != nil {
|
||||
return e.InternalServerError("", err)
|
||||
}
|
||||
|
||||
// Sync probes to agent
|
||||
h.syncProbesToAgent(systemID)
|
||||
|
||||
return e.JSON(http.StatusOK, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
// getNetworkProbeStats handles GET /api/beszel/network-probe-stats
|
||||
func (h *Hub) getNetworkProbeStats(e *core.RequestEvent) error {
|
||||
systemID := e.Request.URL.Query().Get("system")
|
||||
statsType := e.Request.URL.Query().Get("type")
|
||||
if systemID == "" {
|
||||
return e.BadRequestError("system parameter required", nil)
|
||||
}
|
||||
if statsType == "" {
|
||||
statsType = "1m"
|
||||
}
|
||||
|
||||
system, err := h.sm.GetSystem(systemID)
|
||||
if err != nil || !system.HasUser(e.App, e.Auth) {
|
||||
return e.NotFoundError("", nil)
|
||||
}
|
||||
|
||||
records, err := e.App.FindRecordsByFilter(
|
||||
"network_probe_stats",
|
||||
"system = {:system} && type = {:type}",
|
||||
"created",
|
||||
0, 0,
|
||||
dbx.Params{"system": systemID, "type": statsType},
|
||||
)
|
||||
if err != nil {
|
||||
return e.InternalServerError("", err)
|
||||
}
|
||||
|
||||
type statsRecord struct {
|
||||
Stats json.RawMessage `json:"stats"`
|
||||
Created string `json:"created"`
|
||||
}
|
||||
|
||||
result := make([]statsRecord, 0, len(records))
|
||||
for _, r := range records {
|
||||
statsJSON, _ := json.Marshal(r.Get("stats"))
|
||||
result = append(result, statsRecord{
|
||||
Stats: statsJSON,
|
||||
Created: r.GetDateTime("created").Time().UTC().Format("2006-01-02 15:04:05.000Z"),
|
||||
})
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// syncProbesToAgent fetches enabled probes for a system and sends them to the agent.
|
||||
func (h *Hub) syncProbesToAgent(systemID string) {
|
||||
system, err := h.sm.GetSystem(systemID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
configs := h.sm.GetProbeConfigsForSystem(systemID)
|
||||
|
||||
go func() {
|
||||
if err := system.SyncNetworkProbes(configs); err != nil {
|
||||
h.Logger().Warn("failed to sync probes to agent", "system", systemID, "err", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func setCollectionAuthSettings(app core.App) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := applyCollectionRules(app, []string{"fingerprints"}, collectionRules{
|
||||
if err := applyCollectionRules(app, []string{"fingerprints", "network_probes"}, collectionRules{
|
||||
list: &systemScopedReadRule,
|
||||
view: &systemScopedReadRule,
|
||||
create: &systemScopedWriteRule,
|
||||
|
||||
@@ -81,6 +81,7 @@ func (h *Hub) StartHub() error {
|
||||
}
|
||||
// register middlewares
|
||||
h.registerMiddlewares(e)
|
||||
// bind events that aren't set up in different
|
||||
// register api routes
|
||||
if err := h.registerApiRoutes(e); err != nil {
|
||||
return err
|
||||
@@ -109,6 +110,8 @@ func (h *Hub) StartHub() error {
|
||||
h.App.OnRecordCreate("users").BindFunc(h.um.InitializeUserRole)
|
||||
h.App.OnRecordCreate("user_settings").BindFunc(h.um.InitializeUserSettings)
|
||||
|
||||
bindNetworkProbesEvents(h)
|
||||
|
||||
pb, ok := h.App.(*pocketbase.PocketBase)
|
||||
if !ok {
|
||||
return errors.New("not a pocketbase app")
|
||||
|
||||
36
internal/hub/probes.go
Normal file
36
internal/hub/probes.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package hub
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
func bindNetworkProbesEvents(h *Hub) {
|
||||
// sync probe to agent on creation
|
||||
h.OnRecordAfterCreateSuccess("network_probes").BindFunc(func(e *core.RecordEvent) error {
|
||||
systemID := e.Record.GetString("system")
|
||||
h.syncProbesToAgent(systemID)
|
||||
return e.Next()
|
||||
})
|
||||
// sync probe to agent on delete
|
||||
h.OnRecordAfterDeleteSuccess("network_probes").BindFunc(func(e *core.RecordEvent) error {
|
||||
systemID := e.Record.GetString("system")
|
||||
h.syncProbesToAgent(systemID)
|
||||
return e.Next()
|
||||
})
|
||||
}
|
||||
|
||||
// syncProbesToAgent fetches enabled probes for a system and sends them to the agent.
|
||||
func (h *Hub) syncProbesToAgent(systemID string) {
|
||||
system, err := h.sm.GetSystem(systemID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
configs := h.sm.GetProbeConfigsForSystem(systemID)
|
||||
|
||||
go func() {
|
||||
if err := system.SyncNetworkProbes(configs); err != nil {
|
||||
h.Logger().Warn("failed to sync probes to agent", "system", systemID, "err", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
Reference in New Issue
Block a user