| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 | package upstreamimport (	"net/http"	"sort"	"github.com/0xJacky/Nginx-UI/internal/upstream"	"github.com/0xJacky/Nginx-UI/model"	"github.com/0xJacky/Nginx-UI/query"	"github.com/gin-gonic/gin"	"github.com/uozi-tech/cosy"	"github.com/uozi-tech/cosy/logger")// UpstreamInfo represents an upstream with its configuration and health statustype UpstreamInfo struct {	Name       string                     `json:"name"`	Servers    []upstream.ProxyTarget     `json:"servers"`	ConfigPath string                     `json:"config_path"`	LastSeen   string                     `json:"last_seen"`	Status     map[string]*upstream.Status `json:"status"`	Enabled    bool                       `json:"enabled"`}// GetUpstreamList returns all upstreams with their configuration and health statusfunc GetUpstreamList(c *gin.Context) {	service := upstream.GetUpstreamService()	// Get all upstream definitions	upstreams := service.GetAllUpstreamDefinitions()	// Get availability map	availabilityMap := service.GetAvailabilityMap()	// Get all upstream configurations from database	u := query.UpstreamConfig	configs, err := u.Find()	if err != nil {		cosy.ErrHandler(c, err)		return	}	// Create a map for quick lookup of enabled status by upstream name	configMap := make(map[string]bool)	for _, config := range configs {		configMap[config.Socket] = config.Enabled	}	// Build response	result := make([]UpstreamInfo, 0, len(upstreams))	for name, def := range upstreams {		// Get enabled status from database, default to true if not found		enabled := true		if val, exists := configMap[name]; exists {			enabled = val		}		// Get status for each server in this upstream		serverStatus := make(map[string]*upstream.Status)		for _, server := range def.Servers {			key := formatSocketAddress(server.Host, server.Port)			if status, exists := availabilityMap[key]; exists {				serverStatus[key] = status			}		}		info := UpstreamInfo{			Name:       name,			Servers:    def.Servers,			ConfigPath: def.ConfigPath,			LastSeen:   def.LastSeen.Format("2006-01-02 15:04:05"),			Status:     serverStatus,			Enabled:    enabled,		}		result = append(result, info)	}	// Sort by name for stable ordering	sort.Slice(result, func(i, j int) bool {		return result[i].Name < result[j].Name	})	c.JSON(http.StatusOK, gin.H{		"data": result,	})}// UpdateUpstreamConfigRequest represents the request body for updating upstream configtype UpdateUpstreamConfigRequest struct {	Enabled bool `json:"enabled"`}// UpdateUpstreamConfig updates the enabled status of an upstreamfunc UpdateUpstreamConfig(c *gin.Context) {	name := c.Param("name")	var req UpdateUpstreamConfigRequest	if err := c.ShouldBindJSON(&req); err != nil {		cosy.ErrHandler(c, err)		return	}	u := query.UpstreamConfig	// Check if config exists	config, err := u.Where(u.Socket.Eq(name)).First()	if err != nil {		// Create new config if not found		config = &model.UpstreamConfig{			Socket:  name,			Enabled: req.Enabled,		}		if err := u.Create(config); err != nil {			logger.Error("Failed to create upstream config:", err)			cosy.ErrHandler(c, err)			return		}	} else {		// Update existing config		if _, err := u.Where(u.Socket.Eq(name)).Update(u.Enabled, req.Enabled); err != nil {			logger.Error("Failed to update upstream config:", err)			cosy.ErrHandler(c, err)			return		}	}	c.JSON(http.StatusOK, gin.H{		"message": "Upstream config updated successfully",	})}
 |