123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- package handlers
- import (
- "fmt"
- "net/http"
- "strconv"
- "git.linuxforward.com/byop/byop-engine/dbstore"
- "git.linuxforward.com/byop/byop-engine/models"
- "github.com/gin-gonic/gin"
- )
- // DeploymentHandler handles deployment-related operations and contains integrated service logic
- type DeploymentHandler struct {
- store *dbstore.SQLiteStore
- }
- // NewDeploymentHandler creates a new DeploymentHandler
- func NewDeploymentHandler(store *dbstore.SQLiteStore) *DeploymentHandler {
- return &DeploymentHandler{
- store: store,
- }
- }
- // ListDeployments returns all deployments with optional filtering
- func (h *DeploymentHandler) ListDeployments(c *gin.Context) {
- filter := make(map[string]interface{})
- ctx := c.Request.Context()
- // Attempt to bind query parameters, but allow empty filters
- if err := c.ShouldBindQuery(&filter); err != nil && len(filter) > 0 {
- appErr := models.NewErrValidation("invalid_query_params", nil, err)
- models.RespondWithError(c, appErr)
- return
- }
- deployments, err := h.store.GetAllDeployments(ctx)
- if err != nil {
- appErr := models.NewErrInternalServer("failed_list_deployments", fmt.Errorf("Failed to list deployments: %w", err))
- models.RespondWithError(c, appErr)
- return
- }
- // If empty, return an empty list
- if len(deployments) == 0 {
- c.JSON(http.StatusOK, []models.Deployment{})
- return
- }
- c.JSON(http.StatusOK, deployments)
- }
- // CreateDeployment creates a new deployment
- func (h *DeploymentHandler) CreateDeployment(c *gin.Context) {
- var deployment models.Deployment
- ctx := c.Request.Context()
- if err := c.ShouldBindJSON(&deployment); err != nil {
- appErr := models.NewErrValidation("invalid_request_body", nil, err)
- models.RespondWithError(c, appErr)
- return
- }
- // Basic validation
- validationErrors := make(map[string]string)
- if deployment.AppId == 0 {
- validationErrors["app_id"] = "App ID is required"
- }
- if deployment.Environment == "" {
- validationErrors["environment"] = "Environment is required"
- }
- if len(validationErrors) > 0 {
- appErr := models.NewErrValidation("deployment_validation_failed", validationErrors, nil)
- models.RespondWithError(c, appErr)
- return
- }
- // Set default status
- if deployment.Status == "" {
- deployment.Status = "pending"
- }
- // TODO: Add complex deployment logic with cloud providers
- id, err := h.store.CreateDeployment(ctx, deployment)
- if err != nil {
- appErr := models.NewErrInternalServer("failed_create_deployment", fmt.Errorf("Failed to create deployment: %w", err))
- models.RespondWithError(c, appErr)
- return
- }
- // Set the generated ID
- deployment.ID = id
- c.JSON(http.StatusCreated, deployment)
- }
- // GetDeployment returns a specific deployment
- func (h *DeploymentHandler) GetDeployment(c *gin.Context) {
- idStr := c.Param("id")
- ctx := c.Request.Context()
- id, err := strconv.ParseInt(idStr, 10, 64)
- if err != nil {
- appErr := models.NewErrValidation("invalid_deployment_id_format", map[string]string{"id": "Invalid deployment ID format"}, err)
- models.RespondWithError(c, appErr)
- return
- }
- deployment, err := h.store.GetDeploymentByID(ctx, int(id))
- if err != nil {
- models.RespondWithError(c, err)
- return
- }
- c.JSON(http.StatusOK, deployment)
- }
- // UpdateDeployment updates a deployment
- func (h *DeploymentHandler) UpdateDeployment(c *gin.Context) {
- idStr := c.Param("id")
- ctx := c.Request.Context()
- id, err := strconv.ParseInt(idStr, 10, 64)
- if err != nil {
- appErr := models.NewErrValidation("invalid_deployment_id_format", map[string]string{"id": "Invalid deployment ID format"}, err)
- models.RespondWithError(c, appErr)
- return
- }
- var updatedDeployment models.Deployment
- if err := c.ShouldBindJSON(&updatedDeployment); err != nil {
- appErr := models.NewErrValidation("invalid_request_body", nil, err)
- models.RespondWithError(c, appErr)
- return
- }
- // Ensure the ID matches the URL parameter
- updatedDeployment.ID = int(id)
- // Basic validation for update
- validationErrors := make(map[string]string)
- if updatedDeployment.AppId == 0 {
- validationErrors["app_id"] = "App ID is required"
- }
- if updatedDeployment.Environment == "" {
- validationErrors["environment"] = "Environment is required"
- }
- if len(validationErrors) > 0 {
- appErr := models.NewErrValidation("deployment_update_validation_failed", validationErrors, nil)
- models.RespondWithError(c, appErr)
- return
- }
- if err := h.store.UpdateDeployment(ctx, &updatedDeployment); err != nil {
- models.RespondWithError(c, err)
- return
- }
- c.JSON(http.StatusOK, updatedDeployment)
- }
- // DeleteDeployment deletes a deployment
- func (h *DeploymentHandler) DeleteDeployment(c *gin.Context) {
- idStr := c.Param("id")
- ctx := c.Request.Context()
- id, err := strconv.ParseInt(idStr, 10, 64)
- if err != nil {
- appErr := models.NewErrValidation("invalid_deployment_id_format", map[string]string{"id": "Invalid deployment ID format"}, err)
- models.RespondWithError(c, appErr)
- return
- }
- if err := h.store.DeleteDeployment(ctx, int(id)); err != nil {
- models.RespondWithError(c, err)
- return
- }
- c.JSON(http.StatusOK, gin.H{"message": "Deployment deleted successfully"})
- }
- // UpdateDeploymentStatus updates the status of a deployment
- func (h *DeploymentHandler) UpdateDeploymentStatus(c *gin.Context) {
- idStr := c.Param("id")
- ctx := c.Request.Context()
- id, err := strconv.ParseInt(idStr, 10, 64)
- if err != nil {
- appErr := models.NewErrValidation("invalid_deployment_id_format", map[string]string{"id": "Invalid deployment ID format"}, err)
- models.RespondWithError(c, appErr)
- return
- }
- var statusUpdate struct {
- Status string `json:"status" binding:"required"`
- }
- if err := c.ShouldBindJSON(&statusUpdate); err != nil {
- appErr := models.NewErrValidation("invalid_status_update_body", nil, err)
- models.RespondWithError(c, appErr)
- return
- }
- // Get current deployment
- deployment, err := h.store.GetDeploymentByID(ctx, int(id))
- if err != nil {
- models.RespondWithError(c, err)
- return
- }
- // Update the status
- deployment.Status = statusUpdate.Status
- if err := h.store.UpdateDeployment(ctx, deployment); err != nil {
- if _, ok := err.(models.CustomError); !ok {
- err = models.NewErrInternalServer("failed_update_deployment_status", fmt.Errorf("Failed to update deployment status: %w", err))
- }
- models.RespondWithError(c, err)
- return
- }
- c.Status(http.StatusOK)
- }
- // GetDeploymentsByClient returns all deployments for a specific client
- func (h *DeploymentHandler) GetDeploymentsByClient(c *gin.Context) {
- clientIDStr := c.Param("clientId")
- ctx := c.Request.Context()
- clientID, err := strconv.ParseInt(clientIDStr, 10, 64)
- if err != nil {
- appErr := models.NewErrValidation("invalid_client_id_format", map[string]string{"clientId": "Invalid client ID format"}, err)
- models.RespondWithError(c, appErr)
- return
- }
- deployments, err := h.store.GetDeploymentsByClientID(ctx, int(clientID))
- if err != nil {
- if _, ok := err.(models.CustomError); !ok {
- err = models.NewErrInternalServer("failed_fetch_deployments_by_client", fmt.Errorf("Failed to fetch deployments for client %d: %w", clientID, err))
- }
- models.RespondWithError(c, err)
- return
- }
- c.JSON(http.StatusOK, deployments)
- }
- // GetDeploymentsByApp returns all deployments for a specific app
- func (h *DeploymentHandler) GetDeploymentsByApp(c *gin.Context) {
- appIDStr := c.Param("appId")
- ctx := c.Request.Context()
- appID, err := strconv.ParseInt(appIDStr, 10, 64)
- if err != nil {
- appErr := models.NewErrValidation("invalid_app_id_format", map[string]string{"appId": "Invalid app ID format"}, err)
- models.RespondWithError(c, appErr)
- return
- }
- deployments, err := h.store.GetDeploymentsByAppID(ctx, int(appID))
- if err != nil {
- if _, ok := err.(models.CustomError); !ok {
- err = models.NewErrInternalServer("failed_fetch_deployments_by_app", fmt.Errorf("Failed to fetch deployments for app %d: %w", appID, err))
- }
- models.RespondWithError(c, err)
- return
- }
- c.JSON(http.StatusOK, deployments)
- }
- // GetDeploymentsByUser returns all deployments created by a specific user
- func (h *DeploymentHandler) GetDeploymentsByUser(c *gin.Context) {
- userIDStr := c.Param("userId")
- ctx := c.Request.Context()
- userID, err := strconv.ParseInt(userIDStr, 10, 64)
- if err != nil {
- appErr := models.NewErrValidation("invalid_user_id_format", map[string]string{"userId": "Invalid user ID format"}, err)
- models.RespondWithError(c, appErr)
- return
- }
- deployments, err := h.store.GetDeploymentsByUserID(ctx, int(userID))
- if err != nil {
- if _, ok := err.(models.CustomError); !ok {
- err = models.NewErrInternalServer("failed_fetch_deployments_by_user", fmt.Errorf("Failed to fetch deployments for user %d: %w", userID, err))
- }
- models.RespondWithError(c, err)
- return
- }
- c.JSON(http.StatusOK, deployments)
- }
|