161 lines
4.2 KiB
Go
161 lines
4.2 KiB
Go
package clusteradmin
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"proxui/backend/internal/cluster"
|
|
)
|
|
|
|
type Repository interface {
|
|
UpsertCluster(ctx context.Context, cluster cluster.Cluster) (cluster.Cluster, error)
|
|
SetClusterStatus(ctx context.Context, id string, status string) (cluster.Cluster, bool, error)
|
|
}
|
|
|
|
type Handler struct {
|
|
repository Repository
|
|
}
|
|
|
|
func NewHandler(repository Repository) Handler {
|
|
return Handler{repository: repository}
|
|
}
|
|
|
|
func (h Handler) CreateCluster(w http.ResponseWriter, r *http.Request) {
|
|
var request upsertClusterRequest
|
|
if !decodeJSON(w, r, &request) {
|
|
return
|
|
}
|
|
|
|
saved, err := h.repository.UpsertCluster(r.Context(), cluster.Cluster{
|
|
Name: request.Name,
|
|
APIEndpoint: request.APIEndpoint,
|
|
TLSFingerprint: request.TLSFingerprint,
|
|
TokenID: request.TokenID,
|
|
TokenSecret: request.TokenSecret,
|
|
Status: request.Status,
|
|
})
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "cluster_upsert_failed")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusCreated, clusterResponseFromCluster(saved))
|
|
}
|
|
|
|
func (h Handler) UpdateCluster(w http.ResponseWriter, r *http.Request) {
|
|
clusterID := r.PathValue("clusterID")
|
|
if clusterID == "" {
|
|
writeError(w, http.StatusBadRequest, "cluster_id_required")
|
|
return
|
|
}
|
|
|
|
var request upsertClusterRequest
|
|
if !decodeJSON(w, r, &request) {
|
|
return
|
|
}
|
|
|
|
saved, err := h.repository.UpsertCluster(r.Context(), cluster.Cluster{
|
|
ID: clusterID,
|
|
Name: request.Name,
|
|
APIEndpoint: request.APIEndpoint,
|
|
TLSFingerprint: request.TLSFingerprint,
|
|
TokenID: request.TokenID,
|
|
TokenSecret: request.TokenSecret,
|
|
Status: request.Status,
|
|
})
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "cluster_upsert_failed")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, clusterResponseFromCluster(saved))
|
|
}
|
|
|
|
func (h Handler) SetClusterStatus(w http.ResponseWriter, r *http.Request) {
|
|
clusterID := r.PathValue("clusterID")
|
|
if clusterID == "" {
|
|
writeError(w, http.StatusBadRequest, "cluster_id_required")
|
|
return
|
|
}
|
|
|
|
var request setStatusRequest
|
|
if !decodeJSON(w, r, &request) {
|
|
return
|
|
}
|
|
if strings.TrimSpace(request.Status) == "" {
|
|
writeError(w, http.StatusBadRequest, "status_required")
|
|
return
|
|
}
|
|
|
|
updated, found, err := h.repository.SetClusterStatus(r.Context(), clusterID, request.Status)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "cluster_status_update_failed")
|
|
return
|
|
}
|
|
if !found {
|
|
writeError(w, http.StatusNotFound, "cluster_not_found")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, clusterResponseFromCluster(updated))
|
|
}
|
|
|
|
type upsertClusterRequest struct {
|
|
Name string `json:"name"`
|
|
APIEndpoint string `json:"api_endpoint"`
|
|
TLSFingerprint string `json:"tls_fingerprint"`
|
|
TokenID string `json:"token_id"`
|
|
TokenSecret string `json:"token_secret"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
type setStatusRequest struct {
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
type clusterResponse struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
APIEndpoint string `json:"api_endpoint"`
|
|
TLSFingerprint string `json:"tls_fingerprint"`
|
|
TokenID string `json:"token_id"`
|
|
Status string `json:"status"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
func clusterResponseFromCluster(cluster cluster.Cluster) clusterResponse {
|
|
return clusterResponse{
|
|
ID: cluster.ID,
|
|
Name: cluster.Name,
|
|
APIEndpoint: cluster.APIEndpoint,
|
|
TLSFingerprint: cluster.TLSFingerprint,
|
|
TokenID: cluster.TokenID,
|
|
Status: cluster.Status,
|
|
CreatedAt: cluster.CreatedAt,
|
|
}
|
|
}
|
|
|
|
func decodeJSON(w http.ResponseWriter, r *http.Request, target any) bool {
|
|
defer r.Body.Close()
|
|
decoder := json.NewDecoder(r.Body)
|
|
decoder.DisallowUnknownFields()
|
|
if err := decoder.Decode(target); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid_json")
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func writeJSON(w http.ResponseWriter, status int, body any) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(status)
|
|
_ = json.NewEncoder(w).Encode(body)
|
|
}
|
|
|
|
func writeError(w http.ResponseWriter, status int, message string) {
|
|
writeJSON(w, status, map[string]string{"error": message})
|
|
}
|