initial commit
This commit is contained in:
@@ -0,0 +1,352 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"nodemaster/models"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// NodeController manages the current host node.
|
||||
type NodeController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// @Title GetNode
|
||||
// @Description get current node info including runtime config_file path
|
||||
// @Success 200 {object} models.NodeInfo
|
||||
// @router / [get]
|
||||
func (c *NodeController) Get() {
|
||||
n := models.GetLocalNode()
|
||||
c.Data["json"] = map[string]interface{}{
|
||||
"hostname": n.Hostname,
|
||||
"description": n.Description,
|
||||
"update_history": n.UpdateHistory,
|
||||
"backup": n.Backup,
|
||||
"config_file": models.ConfigPath(),
|
||||
"restic_password_set": n.ResticPassword != "",
|
||||
}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title UpdateNode
|
||||
// @Description update current node hostname, description, or restic_password (the repository password used to encrypt/decrypt all restic backup targets on this node)
|
||||
// @Param body body models.NodeInfo true "fields to update"
|
||||
// @Success 200 {string} update success
|
||||
// @Failure 400 invalid body
|
||||
// @router / [put]
|
||||
func (c *NodeController) Put() {
|
||||
var n models.NodeInfo
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &n); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
if err := models.UpdateLocalNode(n); err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]string{"message": "update success"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetUpdates
|
||||
// @Description list update history
|
||||
// @Success 200 {object} []models.UpdateRecord
|
||||
// @router /updates [get]
|
||||
func (c *NodeController) GetUpdates() {
|
||||
c.Data["json"] = models.GetUpdateHistory()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetUpdate
|
||||
// @Description get a single update record
|
||||
// @Param id path string true "update record id"
|
||||
// @Success 200 {object} models.UpdateRecord
|
||||
// @Failure 404 not found
|
||||
// @router /updates/:id [get]
|
||||
func (c *NodeController) GetUpdate() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
r, err := models.GetUpdateRecord(id)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = r
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title AddUpdate
|
||||
// @Description record a new update entry
|
||||
// @Param body body models.UpdateRecord true "update record"
|
||||
// @Success 201 {object} models.UpdateRecord
|
||||
// @Failure 400 invalid body
|
||||
// @router /updates [post]
|
||||
func (c *NodeController) AddUpdate() {
|
||||
var r models.UpdateRecord
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &r); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
record, err := models.AddUpdateRecord(r)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.SetStatus(201)
|
||||
c.Data["json"] = record
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title DeleteUpdate
|
||||
// @Description delete an update record
|
||||
// @Param id path string true "update record id"
|
||||
// @Success 200 {string} delete success
|
||||
// @Failure 404 not found
|
||||
// @router /updates/:id [delete]
|
||||
func (c *NodeController) DeleteUpdate() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
if err := models.DeleteUpdateRecord(id); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]string{"message": "delete success"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetBackup
|
||||
// @Description get node backup configuration
|
||||
// @Success 200 {object} models.BackupConfig
|
||||
// @router /backup [get]
|
||||
func (c *NodeController) GetBackup() {
|
||||
c.Data["json"] = models.GetNodeBackupConfig()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title UpdateBackup
|
||||
// @Description update node backup configuration
|
||||
// @Param body body models.BackupConfig true "backup config"
|
||||
// @Success 200 {string} update success
|
||||
// @Failure 400 invalid body
|
||||
// @router /backup [put]
|
||||
func (c *NodeController) PutBackup() {
|
||||
var bc models.BackupConfig
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &bc); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
if err := models.UpdateNodeBackupConfig(bc); err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]string{"message": "update success"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title Scan
|
||||
// @Description scan compose folders and index discovered services; accepts optional {"folder":"/path"} body
|
||||
// @Param body body object false "optional folder override"
|
||||
// @Success 200 {object} models.ScanResult
|
||||
// @router /scan [post]
|
||||
func (c *NodeController) Scan() {
|
||||
var req struct {
|
||||
Folder string `json:"folder"`
|
||||
}
|
||||
_ = json.Unmarshal(c.Ctx.Input.RequestBody, &req)
|
||||
result := models.ScanAll(req.Folder)
|
||||
c.Data["json"] = result
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title RunBackup
|
||||
// @Description trigger an immediate node backup across all targets (asynchronous)
|
||||
// @Success 202 {string} backup started
|
||||
// @Failure 400 no targets configured
|
||||
// @router /backup/run [post]
|
||||
func (c *NodeController) RunBackup() {
|
||||
bc := models.GetNodeBackupConfig()
|
||||
if len(bc.Targets) == 0 {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": "no backup targets configured"}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.SetStatus(202)
|
||||
c.Data["json"] = map[string]string{"message": "backup started"}
|
||||
c.ServeJSON()
|
||||
go func() {
|
||||
_ = models.RunNodeBackup(nil)
|
||||
}()
|
||||
}
|
||||
|
||||
// @Title GetBackupTargets
|
||||
// @Description list node backup target definitions
|
||||
// @Success 200 {object} []models.BackupTarget
|
||||
// @router /backup/targets [get]
|
||||
func (c *NodeController) GetBackupTargets() {
|
||||
c.Data["json"] = models.GetNodeBackupTargets()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title AddBackupTarget
|
||||
// @Description define a new node backup target
|
||||
// @Param body body models.BackupTarget true "backup target definition"
|
||||
// @Success 201 {object} models.BackupTarget
|
||||
// @Failure 400 invalid body
|
||||
// @router /backup/targets [post]
|
||||
func (c *NodeController) AddBackupTarget() {
|
||||
var t models.BackupTarget
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &t); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
created, err := models.AddNodeBackupTarget(t)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.SetStatus(201)
|
||||
c.Data["json"] = created
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetBackupTarget
|
||||
// @Description get a node backup target by id
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Success 200 {object} models.BackupTarget
|
||||
// @Failure 404 not found
|
||||
// @router /backup/targets/:tid [get]
|
||||
func (c *NodeController) GetBackupTarget() {
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
t, err := models.GetNodeBackupTarget(tid)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = t
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title PutBackupTarget
|
||||
// @Description update a node backup target definition
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Param body body models.BackupTarget true "updated backup target"
|
||||
// @Success 200 {object} models.BackupTarget
|
||||
// @Failure 400 invalid body
|
||||
// @Failure 404 not found
|
||||
// @router /backup/targets/:tid [put]
|
||||
func (c *NodeController) PutBackupTarget() {
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
var t models.BackupTarget
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &t); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
updated, err := models.UpdateNodeBackupTarget(tid, t)
|
||||
if err != nil {
|
||||
status := 404
|
||||
if err.Error() != "backup target not found" {
|
||||
status = 400
|
||||
}
|
||||
c.Ctx.Output.SetStatus(status)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = updated
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title DeleteBackupTarget
|
||||
// @Description delete a node backup target definition
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Success 200 {string} delete success
|
||||
// @Failure 404 not found
|
||||
// @router /backup/targets/:tid [delete]
|
||||
func (c *NodeController) DeleteBackupTarget() {
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
if err := models.DeleteNodeBackupTarget(tid); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]string{"message": "delete success"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title RunBackupTarget
|
||||
// @Description trigger an immediate backup for a single node target (asynchronous)
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Success 202 {string} backup started
|
||||
// @Failure 404 not found
|
||||
// @router /backup/targets/:tid/run [post]
|
||||
func (c *NodeController) RunBackupTarget() {
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
if _, err := models.GetNodeBackupTarget(tid); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.SetStatus(202)
|
||||
c.Data["json"] = map[string]string{"message": "backup started"}
|
||||
c.ServeJSON()
|
||||
go func() {
|
||||
_ = models.RunNodeBackup([]string{tid})
|
||||
}()
|
||||
}
|
||||
|
||||
// @Title GetBackupTargetProgress
|
||||
// @Description get the current/last run state for a node backup target
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Success 200 {object} models.RunState
|
||||
// @Failure 404 not found
|
||||
// @router /backup/targets/:tid/progress [get]
|
||||
func (c *NodeController) GetBackupTargetProgress() {
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
if _, err := models.GetNodeBackupTarget(tid); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
state, ok := models.GetProgress("node", tid)
|
||||
if !ok {
|
||||
state = models.RunState{TargetID: tid}
|
||||
}
|
||||
c.Data["json"] = state
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetBackupProgress
|
||||
// @Description get the current/last run state for every node backup target
|
||||
// @Success 200 {object} []models.RunState
|
||||
// @router /backup/progress [get]
|
||||
func (c *NodeController) GetBackupProgress() {
|
||||
c.Data["json"] = models.GetProgressForScope("node")
|
||||
c.ServeJSON()
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"nodemaster/models"
|
||||
"time"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// NodesController manages the registry of remote nodes.
|
||||
type NodesController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// @Title GetAllNodes
|
||||
// @Description list all registered remote nodes
|
||||
// @Success 200 {object} []models.RemoteNode
|
||||
// @router / [get]
|
||||
func (c *NodesController) GetAll() {
|
||||
c.Data["json"] = models.GetAllRemoteNodes()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title AddNode
|
||||
// @Description register a remote node
|
||||
// @Param body body models.RemoteNode true "node to register"
|
||||
// @Success 201 {object} models.RemoteNode
|
||||
// @Failure 400 invalid body
|
||||
// @router / [post]
|
||||
func (c *NodesController) Post() {
|
||||
var n models.RemoteNode
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &n); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
created, err := models.AddRemoteNode(n)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.SetStatus(201)
|
||||
c.Data["json"] = created
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetNode
|
||||
// @Description get a remote node by id
|
||||
// @Param id path string true "node id"
|
||||
// @Success 200 {object} models.RemoteNode
|
||||
// @Failure 404 not found
|
||||
// @router /:id [get]
|
||||
func (c *NodesController) Get() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
n, err := models.GetRemoteNode(id)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = n
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title UpdateNode
|
||||
// @Description update a remote node
|
||||
// @Param id path string true "node id"
|
||||
// @Param body body models.RemoteNode true "updated node data"
|
||||
// @Success 200 {object} models.RemoteNode
|
||||
// @Failure 400 invalid body
|
||||
// @Failure 404 not found
|
||||
// @router /:id [put]
|
||||
func (c *NodesController) Put() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
var n models.RemoteNode
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &n); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
updated, err := models.UpdateRemoteNode(id, n)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = updated
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title DeleteNode
|
||||
// @Description delete a remote node
|
||||
// @Param id path string true "node id"
|
||||
// @Success 200 {string} delete success
|
||||
// @Failure 404 not found
|
||||
// @router /:id [delete]
|
||||
func (c *NodesController) Delete() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
if err := models.DeleteRemoteNode(id); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]string{"message": "delete success"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
type nodeServices struct {
|
||||
Node models.RemoteNode `json:"node"`
|
||||
Services []models.Service `json:"services"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// @Title GetAggregated
|
||||
// @Description query all registered nodes for their services and return an aggregated view
|
||||
// @Success 200 {object} []nodeServices
|
||||
// @router /aggregated [get]
|
||||
func (c *NodesController) GetAggregated() {
|
||||
nodes := models.GetAllRemoteNodes()
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
results := make([]nodeServices, 0, len(nodes))
|
||||
|
||||
for _, node := range nodes {
|
||||
entry := nodeServices{Node: node}
|
||||
resp, err := client.Get(node.URL + "/v1/services")
|
||||
if err != nil {
|
||||
entry.Error = err.Error()
|
||||
results = append(results, entry)
|
||||
continue
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
entry.Error = err.Error()
|
||||
results = append(results, entry)
|
||||
continue
|
||||
}
|
||||
var svcs []models.Service
|
||||
if err := json.Unmarshal(body, &svcs); err != nil {
|
||||
entry.Error = "failed to parse services: " + err.Error()
|
||||
} else {
|
||||
entry.Services = svcs
|
||||
}
|
||||
results = append(results, entry)
|
||||
}
|
||||
|
||||
c.Data["json"] = results
|
||||
c.ServeJSON()
|
||||
}
|
||||
@@ -0,0 +1,397 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"nodemaster/models"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// ServicesController manages services on this host.
|
||||
type ServicesController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// @Title GetAllServices
|
||||
// @Description list all services
|
||||
// @Success 200 {object} []models.Service
|
||||
// @router / [get]
|
||||
func (c *ServicesController) GetAll() {
|
||||
c.Data["json"] = models.GetAllServices()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title AddService
|
||||
// @Description register a new service
|
||||
// @Param body body models.Service true "service definition"
|
||||
// @Success 201 {object} models.Service
|
||||
// @Failure 400 invalid body
|
||||
// @router / [post]
|
||||
func (c *ServicesController) Post() {
|
||||
var s models.Service
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &s); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
created, err := models.AddService(s)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.SetStatus(201)
|
||||
c.Data["json"] = created
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetService
|
||||
// @Description get a service by id
|
||||
// @Param id path string true "service id"
|
||||
// @Success 200 {object} models.Service
|
||||
// @Failure 404 not found
|
||||
// @router /:id [get]
|
||||
func (c *ServicesController) Get() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
s, err := models.GetService(id)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = s
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title UpdateService
|
||||
// @Description update a service definition
|
||||
// @Param id path string true "service id"
|
||||
// @Param body body models.Service true "updated service data"
|
||||
// @Success 200 {object} models.Service
|
||||
// @Failure 400 invalid body
|
||||
// @Failure 404 not found
|
||||
// @router /:id [put]
|
||||
func (c *ServicesController) Put() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
var s models.Service
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &s); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
updated, err := models.UpdateService(id, s)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = updated
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title DeleteService
|
||||
// @Description delete a service
|
||||
// @Param id path string true "service id"
|
||||
// @Success 200 {string} delete success
|
||||
// @Failure 404 not found
|
||||
// @router /:id [delete]
|
||||
func (c *ServicesController) Delete() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
if err := models.DeleteService(id); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]string{"message": "delete success"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title StartService
|
||||
// @Description start a service via its compose file
|
||||
// @Param id path string true "service id"
|
||||
// @Success 200 {string} started
|
||||
// @Failure 404 not found
|
||||
// @router /:id/start [post]
|
||||
func (c *ServicesController) Start() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
svc, err := models.GetService(id)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
if err := models.StartService(svc); err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
_ = models.UpdateServiceStatus(id, "up")
|
||||
c.Data["json"] = map[string]string{"message": "service started"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title StopService
|
||||
// @Description stop a service via its compose file
|
||||
// @Param id path string true "service id"
|
||||
// @Success 200 {string} stopped
|
||||
// @Failure 404 not found
|
||||
// @router /:id/stop [post]
|
||||
func (c *ServicesController) Stop() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
svc, err := models.GetService(id)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
if err := models.StopService(svc); err != nil {
|
||||
_ = models.UpdateServiceStatus(id, "down")
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
_ = models.UpdateServiceStatus(id, "down")
|
||||
c.Data["json"] = map[string]string{"message": "service stopped"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title BackupService
|
||||
// @Description trigger an immediate backup for a service across all targets (asynchronous)
|
||||
// @Param id path string true "service id"
|
||||
// @Success 202 {string} backup started
|
||||
// @Failure 400 no backup configured
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup [post]
|
||||
func (c *ServicesController) Backup() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
svc, err := models.GetService(id)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
if svc.Backup == nil || len(svc.Backup.Targets) == 0 {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": "no backup targets configured for this service"}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
c.Ctx.Output.SetStatus(202)
|
||||
c.Data["json"] = map[string]string{
|
||||
"message": "backup started",
|
||||
"started": fmt.Sprintf("%s", time.Now().UTC().Format(time.RFC3339)),
|
||||
}
|
||||
c.ServeJSON()
|
||||
|
||||
go func() {
|
||||
_ = models.RunServiceBackup(id, nil)
|
||||
}()
|
||||
}
|
||||
|
||||
// @Title GetServiceBackupTargets
|
||||
// @Description list a service's backup target definitions
|
||||
// @Param id path string true "service id"
|
||||
// @Success 200 {object} []models.BackupTarget
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup/targets [get]
|
||||
func (c *ServicesController) GetBackupTargets() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
targets, err := models.GetServiceBackupTargets(id)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = targets
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title AddServiceBackupTarget
|
||||
// @Description define a new backup target for a service
|
||||
// @Param id path string true "service id"
|
||||
// @Param body body models.BackupTarget true "backup target definition"
|
||||
// @Success 201 {object} models.BackupTarget
|
||||
// @Failure 400 invalid body
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup/targets [post]
|
||||
func (c *ServicesController) AddBackupTarget() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
var t models.BackupTarget
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &t); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
created, err := models.AddServiceBackupTarget(id, t)
|
||||
if err != nil {
|
||||
status := 400
|
||||
if err.Error() == "service not found" {
|
||||
status = 404
|
||||
}
|
||||
c.Ctx.Output.SetStatus(status)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.SetStatus(201)
|
||||
c.Data["json"] = created
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetServiceBackupTarget
|
||||
// @Description get a service backup target by id
|
||||
// @Param id path string true "service id"
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Success 200 {object} models.BackupTarget
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup/targets/:tid [get]
|
||||
func (c *ServicesController) GetBackupTarget() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
t, err := models.GetServiceBackupTarget(id, tid)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = t
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title PutServiceBackupTarget
|
||||
// @Description update a service backup target definition
|
||||
// @Param id path string true "service id"
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Param body body models.BackupTarget true "updated backup target"
|
||||
// @Success 200 {object} models.BackupTarget
|
||||
// @Failure 400 invalid body
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup/targets/:tid [put]
|
||||
func (c *ServicesController) PutBackupTarget() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
var t models.BackupTarget
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &t); err != nil {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
updated, err := models.UpdateServiceBackupTarget(id, tid, t)
|
||||
if err != nil {
|
||||
status := 400
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
status = 404
|
||||
}
|
||||
c.Ctx.Output.SetStatus(status)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = updated
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title DeleteServiceBackupTarget
|
||||
// @Description delete a service backup target definition
|
||||
// @Param id path string true "service id"
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Success 200 {string} delete success
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup/targets/:tid [delete]
|
||||
func (c *ServicesController) DeleteBackupTarget() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
if err := models.DeleteServiceBackupTarget(id, tid); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]string{"message": "delete success"}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title RunServiceBackupTarget
|
||||
// @Description trigger an immediate backup for a single service target (asynchronous)
|
||||
// @Param id path string true "service id"
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Success 202 {string} backup started
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup/targets/:tid/run [post]
|
||||
func (c *ServicesController) RunBackupTarget() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
if _, err := models.GetServiceBackupTarget(id, tid); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.SetStatus(202)
|
||||
c.Data["json"] = map[string]string{"message": "backup started"}
|
||||
c.ServeJSON()
|
||||
go func() {
|
||||
_ = models.RunServiceBackup(id, []string{tid})
|
||||
}()
|
||||
}
|
||||
|
||||
// @Title GetServiceBackupTargetProgress
|
||||
// @Description get the current/last run state for a service backup target
|
||||
// @Param id path string true "service id"
|
||||
// @Param tid path string true "backup target id"
|
||||
// @Success 200 {object} models.RunState
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup/targets/:tid/progress [get]
|
||||
func (c *ServicesController) GetBackupTargetProgress() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
tid := c.Ctx.Input.Param(":tid")
|
||||
if _, err := models.GetServiceBackupTarget(id, tid); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
state, ok := models.GetProgress("svc:"+id, tid)
|
||||
if !ok {
|
||||
state = models.RunState{TargetID: tid}
|
||||
}
|
||||
c.Data["json"] = state
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetServiceBackupProgress
|
||||
// @Description get the current/last run state for every backup target of a service
|
||||
// @Param id path string true "service id"
|
||||
// @Success 200 {object} []models.RunState
|
||||
// @Failure 404 not found
|
||||
// @router /:id/backup/progress [get]
|
||||
func (c *ServicesController) GetBackupProgress() {
|
||||
id := c.Ctx.Input.Param(":id")
|
||||
if _, err := models.GetService(id); err != nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = models.GetProgressForScope("svc:" + id)
|
||||
c.ServeJSON()
|
||||
}
|
||||
Reference in New Issue
Block a user