mirror of
https://github.com/DeBrosOfficial/network.git
synced 2026-01-30 22:03:03 +00:00
239 lines
6.8 KiB
Go
239 lines
6.8 KiB
Go
package deployments
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/DeBrosOfficial/network/pkg/deployments"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// ListHandler handles listing deployments
|
|
type ListHandler struct {
|
|
service *DeploymentService
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewListHandler creates a new list handler
|
|
func NewListHandler(service *DeploymentService, logger *zap.Logger) *ListHandler {
|
|
return &ListHandler{
|
|
service: service,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// HandleList lists all deployments for a namespace
|
|
func (h *ListHandler) HandleList(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
namespace := getNamespaceFromContext(ctx)
|
|
if namespace == "" {
|
|
http.Error(w, "Namespace not found in context", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
type deploymentRow struct {
|
|
ID string `db:"id"`
|
|
Namespace string `db:"namespace"`
|
|
Name string `db:"name"`
|
|
Type string `db:"type"`
|
|
Version int `db:"version"`
|
|
Status string `db:"status"`
|
|
ContentCID string `db:"content_cid"`
|
|
HomeNodeID string `db:"home_node_id"`
|
|
Port int `db:"port"`
|
|
Subdomain string `db:"subdomain"`
|
|
CreatedAt time.Time `db:"created_at"`
|
|
UpdatedAt time.Time `db:"updated_at"`
|
|
}
|
|
|
|
var rows []deploymentRow
|
|
query := `
|
|
SELECT id, namespace, name, type, version, status, content_cid, home_node_id, port, subdomain, created_at, updated_at
|
|
FROM deployments
|
|
WHERE namespace = ?
|
|
ORDER BY created_at DESC
|
|
`
|
|
|
|
err := h.service.db.Query(ctx, &rows, query, namespace)
|
|
if err != nil {
|
|
h.logger.Error("Failed to query deployments", zap.Error(err))
|
|
http.Error(w, "Failed to query deployments", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
baseDomain := h.service.BaseDomain()
|
|
deployments := make([]map[string]interface{}, len(rows))
|
|
for i, row := range rows {
|
|
shortNodeID := GetShortNodeID(row.HomeNodeID)
|
|
urls := []string{
|
|
"https://" + row.Name + "." + shortNodeID + "." + baseDomain,
|
|
}
|
|
if row.Subdomain != "" {
|
|
urls = append(urls, "https://"+row.Subdomain+"."+baseDomain)
|
|
}
|
|
|
|
deployments[i] = map[string]interface{}{
|
|
"id": row.ID,
|
|
"namespace": row.Namespace,
|
|
"name": row.Name,
|
|
"type": row.Type,
|
|
"version": row.Version,
|
|
"status": row.Status,
|
|
"content_cid": row.ContentCID,
|
|
"home_node_id": row.HomeNodeID,
|
|
"port": row.Port,
|
|
"subdomain": row.Subdomain,
|
|
"urls": urls,
|
|
"created_at": row.CreatedAt,
|
|
"updated_at": row.UpdatedAt,
|
|
}
|
|
}
|
|
|
|
resp := map[string]interface{}{
|
|
"namespace": namespace,
|
|
"deployments": deployments,
|
|
"total": len(deployments),
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(resp)
|
|
}
|
|
|
|
// HandleGet gets a specific deployment
|
|
func (h *ListHandler) HandleGet(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
namespace := getNamespaceFromContext(ctx)
|
|
if namespace == "" {
|
|
http.Error(w, "Namespace not found in context", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// Support both 'name' and 'id' query parameters
|
|
name := r.URL.Query().Get("name")
|
|
id := r.URL.Query().Get("id")
|
|
|
|
if name == "" && id == "" {
|
|
http.Error(w, "name or id query parameter is required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var deployment *deployments.Deployment
|
|
var err error
|
|
|
|
if id != "" {
|
|
deployment, err = h.service.GetDeploymentByID(ctx, namespace, id)
|
|
} else {
|
|
deployment, err = h.service.GetDeployment(ctx, namespace, name)
|
|
}
|
|
if err != nil {
|
|
if err == deployments.ErrDeploymentNotFound {
|
|
http.Error(w, "Deployment not found", http.StatusNotFound)
|
|
} else {
|
|
h.logger.Error("Failed to get deployment", zap.Error(err))
|
|
http.Error(w, "Failed to get deployment", http.StatusInternalServerError)
|
|
}
|
|
return
|
|
}
|
|
|
|
urls := h.service.BuildDeploymentURLs(deployment)
|
|
|
|
resp := map[string]interface{}{
|
|
"id": deployment.ID,
|
|
"namespace": deployment.Namespace,
|
|
"name": deployment.Name,
|
|
"type": deployment.Type,
|
|
"version": deployment.Version,
|
|
"status": deployment.Status,
|
|
"content_cid": deployment.ContentCID,
|
|
"build_cid": deployment.BuildCID,
|
|
"home_node_id": deployment.HomeNodeID,
|
|
"port": deployment.Port,
|
|
"subdomain": deployment.Subdomain,
|
|
"urls": urls,
|
|
"memory_limit_mb": deployment.MemoryLimitMB,
|
|
"cpu_limit_percent": deployment.CPULimitPercent,
|
|
"disk_limit_mb": deployment.DiskLimitMB,
|
|
"health_check_path": deployment.HealthCheckPath,
|
|
"health_check_interval": deployment.HealthCheckInterval,
|
|
"restart_policy": deployment.RestartPolicy,
|
|
"max_restart_count": deployment.MaxRestartCount,
|
|
"created_at": deployment.CreatedAt,
|
|
"updated_at": deployment.UpdatedAt,
|
|
"deployed_by": deployment.DeployedBy,
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(resp)
|
|
}
|
|
|
|
// HandleDelete deletes a deployment
|
|
func (h *ListHandler) HandleDelete(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
namespace := getNamespaceFromContext(ctx)
|
|
if namespace == "" {
|
|
http.Error(w, "Namespace not found in context", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// Support both 'name' and 'id' query parameters
|
|
name := r.URL.Query().Get("name")
|
|
id := r.URL.Query().Get("id")
|
|
|
|
if name == "" && id == "" {
|
|
http.Error(w, "name or id query parameter is required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
h.logger.Info("Deleting deployment",
|
|
zap.String("namespace", namespace),
|
|
zap.String("name", name),
|
|
zap.String("id", id),
|
|
)
|
|
|
|
// Get deployment
|
|
var deployment *deployments.Deployment
|
|
var err error
|
|
|
|
if id != "" {
|
|
deployment, err = h.service.GetDeploymentByID(ctx, namespace, id)
|
|
} else {
|
|
deployment, err = h.service.GetDeployment(ctx, namespace, name)
|
|
}
|
|
if err != nil {
|
|
if err == deployments.ErrDeploymentNotFound {
|
|
http.Error(w, "Deployment not found", http.StatusNotFound)
|
|
} else {
|
|
http.Error(w, "Failed to get deployment", http.StatusInternalServerError)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Delete deployment record
|
|
query := `DELETE FROM deployments WHERE namespace = ? AND name = ?`
|
|
_, err = h.service.db.Exec(ctx, query, namespace, name)
|
|
if err != nil {
|
|
h.logger.Error("Failed to delete deployment", zap.Error(err))
|
|
http.Error(w, "Failed to delete deployment", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Delete DNS records
|
|
query = `DELETE FROM dns_records WHERE deployment_id = ?`
|
|
_, _ = h.service.db.Exec(ctx, query, deployment.ID)
|
|
|
|
h.logger.Info("Deployment deleted",
|
|
zap.String("id", deployment.ID),
|
|
zap.String("namespace", namespace),
|
|
zap.String("name", name),
|
|
)
|
|
|
|
resp := map[string]interface{}{
|
|
"message": "Deployment deleted successfully",
|
|
"name": name,
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(resp)
|
|
}
|