167 lines
4.8 KiB
Go
167 lines
4.8 KiB
Go
package controller
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
storepkg "github.com/cirruslabs/orchard/internal/controller/store"
|
|
"github.com/cirruslabs/orchard/internal/responder"
|
|
"github.com/cirruslabs/orchard/internal/simplename"
|
|
v1 "github.com/cirruslabs/orchard/pkg/resource/v1"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func (controller *Controller) createWorker(ctx *gin.Context) responder.Responder {
|
|
if responder := controller.authorize(ctx, v1.ServiceAccountRoleComputeWrite); responder != nil {
|
|
return responder
|
|
}
|
|
|
|
var worker v1.Worker
|
|
|
|
if err := ctx.ShouldBindJSON(&worker); err != nil {
|
|
return responder.JSON(http.StatusBadRequest, NewErrorResponse("invalid JSON was provided"))
|
|
}
|
|
|
|
if worker.Name == "" {
|
|
return responder.JSON(http.StatusPreconditionFailed, NewErrorResponse("worker name is empty"))
|
|
} else if err := simplename.Validate(worker.Name); err != nil {
|
|
return responder.JSON(http.StatusPreconditionFailed,
|
|
NewErrorResponse("worker name %v", err))
|
|
}
|
|
|
|
// Provide platform defaults
|
|
if worker.Arch == "" {
|
|
worker.Arch = v1.ArchitectureARM64
|
|
}
|
|
if worker.Runtime == "" {
|
|
worker.Runtime = v1.RuntimeTart
|
|
}
|
|
|
|
currentTime := time.Now()
|
|
if worker.LastSeen.IsZero() {
|
|
worker.LastSeen = currentTime
|
|
}
|
|
worker.CreatedAt = currentTime
|
|
|
|
return controller.storeUpdate(func(txn storepkg.Transaction) responder.Responder {
|
|
// In case there already exist a worker with the same name,
|
|
// update it (to avoid overwriting things like SchedulingPaused)
|
|
// if the request comes from a worker with the same machine ID
|
|
dbWorker, err := txn.GetWorker(worker.Name)
|
|
if err != nil {
|
|
if errors.Is(err, storepkg.ErrNotFound) {
|
|
// Create a new worker
|
|
if err := txn.SetWorker(worker); err != nil {
|
|
return responder.Error(err)
|
|
}
|
|
|
|
return responder.JSON(200, worker)
|
|
}
|
|
|
|
controller.logger.Errorf("failed to check if the worker "+
|
|
"with name %q exists in the DB: %v", worker.Name, err)
|
|
|
|
return responder.Code(http.StatusInternalServerError)
|
|
}
|
|
|
|
// Update an already existing worker
|
|
if worker.MachineID != dbWorker.MachineID {
|
|
return responder.JSON(http.StatusConflict, NewErrorResponse("this worker is managed "+
|
|
"from a different machine ID, delete this worker first to be able to re-create it"))
|
|
}
|
|
|
|
dbWorker.Arch = worker.Arch
|
|
dbWorker.Runtime = worker.Runtime
|
|
dbWorker.LastSeen = worker.LastSeen
|
|
dbWorker.Resources = worker.Resources
|
|
dbWorker.Labels = worker.Labels
|
|
dbWorker.DefaultCPU = worker.DefaultCPU
|
|
dbWorker.DefaultMemory = worker.DefaultMemory
|
|
|
|
if err := txn.SetWorker(*dbWorker); err != nil {
|
|
return responder.Error(err)
|
|
}
|
|
|
|
return responder.JSON(200, dbWorker)
|
|
})
|
|
}
|
|
|
|
func (controller *Controller) updateWorker(ctx *gin.Context) responder.Responder {
|
|
if responder := controller.authorize(ctx, v1.ServiceAccountRoleComputeWrite); responder != nil {
|
|
return responder
|
|
}
|
|
|
|
var userWorker v1.Worker
|
|
|
|
if err := ctx.ShouldBindJSON(&userWorker); err != nil {
|
|
return responder.JSON(http.StatusBadRequest, NewErrorResponse("invalid JSON was provided"))
|
|
}
|
|
|
|
return controller.storeUpdate(func(txn storepkg.Transaction) responder.Responder {
|
|
dbWorker, err := txn.GetWorker(userWorker.Name)
|
|
if err != nil {
|
|
return responder.Error(err)
|
|
}
|
|
|
|
dbWorker.LastSeen = userWorker.LastSeen
|
|
dbWorker.SchedulingPaused = userWorker.SchedulingPaused
|
|
|
|
if err := txn.SetWorker(*dbWorker); err != nil {
|
|
controller.logger.Errorf("failed to update worker in the DB: %v", err)
|
|
|
|
return responder.Code(http.StatusInternalServerError)
|
|
}
|
|
|
|
return responder.JSON(200, &dbWorker)
|
|
})
|
|
}
|
|
|
|
func (controller *Controller) getWorker(ctx *gin.Context) responder.Responder {
|
|
if responder := controller.authorize(ctx, v1.ServiceAccountRoleComputeRead); responder != nil {
|
|
return responder
|
|
}
|
|
|
|
name := ctx.Param("name")
|
|
|
|
return controller.storeView(func(txn storepkg.Transaction) responder.Responder {
|
|
worker, err := txn.GetWorker(name)
|
|
if err != nil {
|
|
return responder.Error(err)
|
|
}
|
|
|
|
return responder.JSON(http.StatusOK, &worker)
|
|
})
|
|
}
|
|
|
|
func (controller *Controller) listWorkers(ctx *gin.Context) responder.Responder {
|
|
if responder := controller.authorize(ctx, v1.ServiceAccountRoleComputeRead); responder != nil {
|
|
return responder
|
|
}
|
|
|
|
return controller.storeView(func(txn storepkg.Transaction) responder.Responder {
|
|
workers, err := txn.ListWorkers()
|
|
if err != nil {
|
|
return responder.Error(err)
|
|
}
|
|
|
|
return responder.JSON(http.StatusOK, &workers)
|
|
})
|
|
}
|
|
|
|
func (controller *Controller) deleteWorker(ctx *gin.Context) responder.Responder {
|
|
if responder := controller.authorize(ctx, v1.ServiceAccountRoleComputeWrite); responder != nil {
|
|
return responder
|
|
}
|
|
|
|
name := ctx.Param("name")
|
|
|
|
return controller.storeUpdate(func(txn storepkg.Transaction) responder.Responder {
|
|
if err := txn.DeleteWorker(name); err != nil {
|
|
return responder.Error(err)
|
|
}
|
|
|
|
return responder.Code(http.StatusOK)
|
|
})
|
|
}
|