417 lines
12 KiB
Go
417 lines
12 KiB
Go
package transport
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/gin-contrib/cors"
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"app-deploy-platform/backend/internal/config"
|
|
"app-deploy-platform/backend/internal/model"
|
|
"app-deploy-platform/backend/internal/service"
|
|
)
|
|
|
|
type routerHandler struct {
|
|
manager *service.Manager
|
|
}
|
|
|
|
type hostPayload struct {
|
|
ID uint `json:"id"`
|
|
Name string `json:"name"`
|
|
InstanceID string `json:"instance_id"`
|
|
PrivateIP string `json:"private_ip"`
|
|
Role string `json:"role"`
|
|
Environment string `json:"environment"`
|
|
Description string `json:"description"`
|
|
TATOnline bool `json:"tat_online"`
|
|
}
|
|
|
|
type instancePayload struct {
|
|
ID uint `json:"id"`
|
|
ServiceName string `json:"service_name"`
|
|
HostID uint `json:"host_id"`
|
|
Port int `json:"port"`
|
|
UnitName string `json:"unit_name"`
|
|
HealthPath string `json:"health_path"`
|
|
ReadyPath string `json:"ready_path"`
|
|
CurrentReleaseID string `json:"current_release_id"`
|
|
}
|
|
|
|
type releasePayload struct {
|
|
ID uint `json:"id"`
|
|
ServiceName string `json:"service_name"`
|
|
ReleaseID string `json:"release_id"`
|
|
GitSHA string `json:"git_sha"`
|
|
COSKey string `json:"cos_key"`
|
|
SHA256 string `json:"sha256"`
|
|
ArtifactURL string `json:"artifact_url"`
|
|
BuildHost string `json:"build_host"`
|
|
}
|
|
|
|
type deploymentPayload struct {
|
|
ServiceName string `json:"service_name"`
|
|
ReleaseID string `json:"release_id"`
|
|
Operation string `json:"operation"`
|
|
Operator string `json:"operator"`
|
|
HostIDs []uint `json:"host_ids"`
|
|
}
|
|
|
|
type buildPayload struct {
|
|
ServiceName string `json:"service_name"`
|
|
ReleaseID string `json:"release_id"`
|
|
Branch string `json:"branch"`
|
|
Operator string `json:"operator"`
|
|
}
|
|
|
|
type releaseRunPayload struct {
|
|
ReleaseID string `json:"release_id"`
|
|
Operator string `json:"operator"`
|
|
}
|
|
|
|
func NewRouter(cfg config.Config, manager *service.Manager) *gin.Engine {
|
|
gin.SetMode(gin.ReleaseMode)
|
|
router := gin.New()
|
|
router.Use(gin.Logger(), gin.Recovery())
|
|
corsConfig := cors.Config{
|
|
AllowOrigins: []string{cfg.Platform.CORSOrigin},
|
|
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
|
AllowHeaders: []string{"Content-Type", "Authorization"},
|
|
AllowCredentials: cfg.Platform.CORSOrigin != "*",
|
|
}
|
|
if cfg.Platform.CORSOrigin == "*" {
|
|
corsConfig.AllowAllOrigins = true
|
|
}
|
|
router.Use(cors.New(corsConfig))
|
|
|
|
handler := &routerHandler{manager: manager}
|
|
|
|
router.GET("/api/healthz", func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
})
|
|
|
|
api := router.Group("/api")
|
|
{
|
|
api.GET("/overview", handler.overview)
|
|
|
|
api.GET("/hosts", handler.listHosts)
|
|
api.POST("/hosts", handler.saveHost)
|
|
api.PUT("/hosts/:id", handler.saveHost)
|
|
api.DELETE("/hosts/:id", handler.deleteHost)
|
|
|
|
api.GET("/instances", handler.listInstances)
|
|
api.POST("/instances", handler.saveInstance)
|
|
api.PUT("/instances/:id", handler.saveInstance)
|
|
api.DELETE("/instances/:id", handler.deleteInstance)
|
|
api.POST("/instances/:id/restart", handler.restartInstance)
|
|
|
|
api.GET("/services", handler.listServices)
|
|
|
|
api.GET("/releases", handler.listReleases)
|
|
api.POST("/releases", handler.saveRelease)
|
|
|
|
api.GET("/builds", handler.listBuilds)
|
|
api.GET("/builds/:id", handler.getBuild)
|
|
api.POST("/builds", handler.createBuild)
|
|
|
|
api.GET("/release-runs", handler.listReleaseRuns)
|
|
api.GET("/release-runs/:id", handler.getReleaseRun)
|
|
api.POST("/release-runs", handler.createReleaseRun)
|
|
|
|
api.GET("/deployments", handler.listDeployments)
|
|
api.GET("/deployments/:id", handler.getDeployment)
|
|
api.POST("/deployments", handler.createDeployment)
|
|
api.POST("/deployments/:id/rollback", handler.rollbackDeployment)
|
|
}
|
|
|
|
return router
|
|
}
|
|
|
|
func (h *routerHandler) overview(c *gin.Context) {
|
|
data, err := h.manager.GetOverview(c.Request.Context())
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) listHosts(c *gin.Context) {
|
|
data, err := h.manager.ListHosts(c.Request.Context())
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) saveHost(c *gin.Context) {
|
|
var payload hostPayload
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
id := payload.ID
|
|
if id == 0 {
|
|
id = uintFromParam(c.Param("id"))
|
|
}
|
|
|
|
host := &model.Host{
|
|
Model: model.Host{}.Model,
|
|
Name: payload.Name,
|
|
InstanceID: payload.InstanceID,
|
|
PrivateIP: payload.PrivateIP,
|
|
Role: payload.Role,
|
|
Environment: payload.Environment,
|
|
Description: payload.Description,
|
|
TATOnline: payload.TATOnline,
|
|
}
|
|
host.ID = id
|
|
|
|
if err := h.manager.SaveHost(c.Request.Context(), host); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, host)
|
|
}
|
|
|
|
func (h *routerHandler) deleteHost(c *gin.Context) {
|
|
if err := h.manager.DeleteHost(c.Request.Context(), uintFromParam(c.Param("id"))); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.Status(http.StatusNoContent)
|
|
}
|
|
|
|
func (h *routerHandler) listInstances(c *gin.Context) {
|
|
data, err := h.manager.ListInstances(c.Request.Context())
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) saveInstance(c *gin.Context) {
|
|
var payload instancePayload
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
id := payload.ID
|
|
if id == 0 {
|
|
id = uintFromParam(c.Param("id"))
|
|
}
|
|
|
|
instance := &model.ServiceInstance{
|
|
ServiceName: payload.ServiceName,
|
|
HostID: payload.HostID,
|
|
Port: payload.Port,
|
|
UnitName: payload.UnitName,
|
|
HealthPath: payload.HealthPath,
|
|
ReadyPath: payload.ReadyPath,
|
|
CurrentReleaseID: payload.CurrentReleaseID,
|
|
}
|
|
instance.ID = id
|
|
|
|
if err := h.manager.SaveInstance(c.Request.Context(), instance); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, instance)
|
|
}
|
|
|
|
func (h *routerHandler) deleteInstance(c *gin.Context) {
|
|
if err := h.manager.DeleteInstance(c.Request.Context(), uintFromParam(c.Param("id"))); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.Status(http.StatusNoContent)
|
|
}
|
|
|
|
func (h *routerHandler) restartInstance(c *gin.Context) {
|
|
operator := c.Query("operator")
|
|
data, err := h.manager.CreateRestartForInstance(c.Request.Context(), uintFromParam(c.Param("id")), operator)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusAccepted, data)
|
|
}
|
|
|
|
func (h *routerHandler) listServices(c *gin.Context) {
|
|
c.JSON(http.StatusOK, h.manager.ListServices(c.Request.Context()))
|
|
}
|
|
|
|
func (h *routerHandler) listReleases(c *gin.Context) {
|
|
data, err := h.manager.ListReleases(c.Request.Context(), c.Query("service_name"))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) saveRelease(c *gin.Context) {
|
|
var payload releasePayload
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
release := &model.Release{
|
|
ServiceName: payload.ServiceName,
|
|
ReleaseID: payload.ReleaseID,
|
|
GitSHA: payload.GitSHA,
|
|
COSKey: payload.COSKey,
|
|
SHA256: payload.SHA256,
|
|
ArtifactURL: payload.ArtifactURL,
|
|
BuildHost: payload.BuildHost,
|
|
}
|
|
release.ID = payload.ID
|
|
|
|
if err := h.manager.SaveRelease(c.Request.Context(), release); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, release)
|
|
}
|
|
|
|
func (h *routerHandler) listBuilds(c *gin.Context) {
|
|
data, err := h.manager.ListBuilds(c.Request.Context())
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) getBuild(c *gin.Context) {
|
|
data, err := h.manager.GetBuild(c.Request.Context(), uintFromParam(c.Param("id")))
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) createBuild(c *gin.Context) {
|
|
var payload buildPayload
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
data, err := h.manager.CreateBuild(c.Request.Context(), service.CreateBuildRequest{
|
|
ServiceName: payload.ServiceName,
|
|
ReleaseID: payload.ReleaseID,
|
|
Branch: payload.Branch,
|
|
Operator: payload.Operator,
|
|
})
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusAccepted, data)
|
|
}
|
|
|
|
func (h *routerHandler) listReleaseRuns(c *gin.Context) {
|
|
data, err := h.manager.ListReleaseRuns(c.Request.Context())
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) getReleaseRun(c *gin.Context) {
|
|
data, err := h.manager.GetReleaseRun(c.Request.Context(), uintFromParam(c.Param("id")))
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) createReleaseRun(c *gin.Context) {
|
|
var payload releaseRunPayload
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
data, err := h.manager.CreateReleaseRun(c.Request.Context(), service.CreateReleaseRunRequest{
|
|
ReleaseID: payload.ReleaseID,
|
|
Operator: payload.Operator,
|
|
})
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusAccepted, data)
|
|
}
|
|
|
|
func (h *routerHandler) listDeployments(c *gin.Context) {
|
|
data, err := h.manager.ListDeployments(c.Request.Context())
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) getDeployment(c *gin.Context) {
|
|
data, err := h.manager.GetDeployment(c.Request.Context(), uintFromParam(c.Param("id")))
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, data)
|
|
}
|
|
|
|
func (h *routerHandler) createDeployment(c *gin.Context) {
|
|
var payload deploymentPayload
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
data, err := h.manager.CreateDeployment(c.Request.Context(), service.CreateDeploymentRequest{
|
|
ServiceName: payload.ServiceName,
|
|
ReleaseID: payload.ReleaseID,
|
|
Operation: payload.Operation,
|
|
Operator: payload.Operator,
|
|
HostIDs: payload.HostIDs,
|
|
})
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusAccepted, data)
|
|
}
|
|
|
|
func (h *routerHandler) rollbackDeployment(c *gin.Context) {
|
|
var payload struct {
|
|
ReleaseID string `json:"release_id"`
|
|
Operator string `json:"operator"`
|
|
}
|
|
if err := c.ShouldBindJSON(&payload); err != nil && err.Error() != "EOF" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
data, err := h.manager.CreateRollback(c.Request.Context(), uintFromParam(c.Param("id")), payload.ReleaseID, payload.Operator)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusAccepted, data)
|
|
}
|
|
|
|
func uintFromParam(raw string) uint {
|
|
value, _ := strconv.ParseUint(raw, 10, 64)
|
|
return uint(value)
|
|
}
|