Skip to content

Commit 7156fdc

Browse files
committed
update
1 parent 54de04c commit 7156fdc

File tree

10 files changed

+974
-284
lines changed

10 files changed

+974
-284
lines changed

api/handlers/datasource.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package handlers
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/gin-gonic/gin"
7+
"github.com/hhftechnology/middleware-manager/models"
8+
"github.com/hhftechnology/middleware-manager/services"
9+
)
10+
11+
// DataSourceHandler handles data source configuration requests
12+
type DataSourceHandler struct {
13+
ConfigManager *services.ConfigManager
14+
}
15+
16+
// NewDataSourceHandler creates a new data source handler
17+
func NewDataSourceHandler(configManager *services.ConfigManager) *DataSourceHandler {
18+
return &DataSourceHandler{
19+
ConfigManager: configManager,
20+
}
21+
}
22+
23+
// GetDataSources returns all configured data sources
24+
func (h *DataSourceHandler) GetDataSources(c *gin.Context) {
25+
sources := h.ConfigManager.GetDataSources()
26+
activeSource := h.ConfigManager.GetActiveSourceName()
27+
28+
c.JSON(http.StatusOK, gin.H{
29+
"active_source": activeSource,
30+
"sources": sources,
31+
})
32+
}
33+
34+
// GetActiveDataSource returns the active data source configuration
35+
func (h *DataSourceHandler) GetActiveDataSource(c *gin.Context) {
36+
sourceConfig, err := h.ConfigManager.GetActiveDataSourceConfig()
37+
if err != nil {
38+
ResponseWithError(c, http.StatusInternalServerError, err.Error())
39+
return
40+
}
41+
42+
c.JSON(http.StatusOK, gin.H{
43+
"name": h.ConfigManager.GetActiveSourceName(),
44+
"config": sourceConfig,
45+
})
46+
}
47+
48+
// SetActiveDataSource sets the active data source
49+
func (h *DataSourceHandler) SetActiveDataSource(c *gin.Context) {
50+
var request struct {
51+
Name string `json:"name" binding:"required"`
52+
}
53+
54+
if err := c.ShouldBindJSON(&request); err != nil {
55+
ResponseWithError(c, http.StatusBadRequest, "Invalid request: "+err.Error())
56+
return
57+
}
58+
59+
if err := h.ConfigManager.SetActiveDataSource(request.Name); err != nil {
60+
ResponseWithError(c, http.StatusBadRequest, err.Error())
61+
return
62+
}
63+
64+
c.JSON(http.StatusOK, gin.H{
65+
"message": "Data source updated successfully",
66+
"name": request.Name,
67+
})
68+
}
69+
70+
// UpdateDataSource updates a data source configuration
71+
func (h *DataSourceHandler) UpdateDataSource(c *gin.Context) {
72+
name := c.Param("name")
73+
if name == "" {
74+
ResponseWithError(c, http.StatusBadRequest, "Data source name is required")
75+
return
76+
}
77+
78+
var config models.DataSourceConfig
79+
if err := c.ShouldBindJSON(&config); err != nil {
80+
ResponseWithError(c, http.StatusBadRequest, "Invalid request: "+err.Error())
81+
return
82+
}
83+
84+
if err := h.ConfigManager.UpdateDataSource(name, config); err != nil {
85+
ResponseWithError(c, http.StatusInternalServerError, err.Error())
86+
return
87+
}
88+
89+
c.JSON(http.StatusOK, gin.H{
90+
"message": "Data source updated successfully",
91+
"name": name,
92+
"config": config,
93+
})
94+
}

api/server.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ func (s *Server) setupRoutes(uiPath string) {
138138
resources.PUT("/:id/config/headers", s.configHandler.UpdateHeadersConfig) // Custom Host headers
139139
resources.PUT("/:id/config/priority", s.configHandler.UpdateRouterPriority) // Router priority
140140
}
141+
// Data source routes
142+
datasource := api.Group("/datasource")
143+
{
144+
datasource.GET("", s.dataSourceHandler.GetDataSources)
145+
datasource.GET("/active", s.dataSourceHandler.GetActiveDataSource)
146+
datasource.PUT("/active", s.dataSourceHandler.SetActiveDataSource)
147+
datasource.PUT("/:name", s.dataSourceHandler.UpdateDataSource)
148+
}
141149
}
142150

143151
// Serve the React app

main.go

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"log"
66
"os"
77
"os/signal"
8+
"path/filepath"
89
"strconv"
910
"strings"
1011
"syscall"
@@ -18,16 +19,17 @@ import (
1819

1920
// Configuration represents the application configuration
2021
type Configuration struct {
21-
PangolinAPIURL string
22-
TraefikConfDir string
23-
DBPath string
24-
Port string
25-
UIPath string
26-
CheckInterval time.Duration
22+
PangolinAPIURL string
23+
TraefikConfDir string
24+
DBPath string
25+
Port string
26+
UIPath string
27+
ConfigDir string
28+
CheckInterval time.Duration
2729
GenerateInterval time.Duration
28-
Debug bool
29-
AllowCORS bool
30-
CORSOrigin string
30+
Debug bool
31+
AllowCORS bool
32+
CORSOrigin string
3133
}
3234

3335
func main() {
@@ -49,7 +51,7 @@ func main() {
4951
defer db.Close()
5052

5153
// Ensure config directory exists
52-
configDir := getEnv("CONFIG_DIR", "/app/config")
54+
configDir := cfg.ConfigDir
5355
if err := config.EnsureConfigDirectory(configDir); err != nil {
5456
log.Printf("Warning: Failed to create config directory: %v", err)
5557
}
@@ -64,11 +66,20 @@ func main() {
6466
log.Printf("Warning: Failed to load default templates: %v", err)
6567
}
6668

69+
// Initialize config manager
70+
configManager, err := services.NewConfigManager(filepath.Join(configDir, "config.json"))
71+
if err != nil {
72+
log.Fatalf("Failed to initialize config manager: %v", err)
73+
}
74+
6775
// Create stop channel for graceful shutdown
6876
stopChan := make(chan struct{})
6977

70-
// Start resource watcher
71-
resourceWatcher := services.NewResourceWatcher(db, cfg.PangolinAPIURL)
78+
// Start resource watcher with config manager
79+
resourceWatcher, err := services.NewResourceWatcher(db, configManager)
80+
if err != nil {
81+
log.Fatalf("Failed to create resource watcher: %v", err)
82+
}
7283
go resourceWatcher.Start(cfg.CheckInterval)
7384

7485
// Start configuration generator
@@ -84,7 +95,7 @@ func main() {
8495
CORSOrigin: cfg.CORSOrigin,
8596
}
8697

87-
server := api.NewServer(db.DB, serverConfig)
98+
server := api.NewServer(db.DB, serverConfig, configManager)
8899
go func() {
89100
if err := server.Start(); err != nil {
90101
log.Printf("Server error: %v", err)
@@ -141,16 +152,17 @@ func loadConfiguration(debug bool) Configuration {
141152
}
142153

143154
return Configuration{
144-
PangolinAPIURL: getEnv("PANGOLIN_API_URL", "http://pangolin:3001/api/v1"),
145-
TraefikConfDir: getEnv("TRAEFIK_CONF_DIR", "/conf"),
146-
DBPath: getEnv("DB_PATH", "/data/middleware.db"),
147-
Port: getEnv("PORT", "3456"),
148-
UIPath: getEnv("UI_PATH", "/app/ui/build"),
149-
CheckInterval: checkInterval,
155+
PangolinAPIURL: getEnv("PANGOLIN_API_URL", "http://pangolin:3001/api/v1"),
156+
TraefikConfDir: getEnv("TRAEFIK_CONF_DIR", "/conf"),
157+
DBPath: getEnv("DB_PATH", "/data/middleware.db"),
158+
Port: getEnv("PORT", "3456"),
159+
UIPath: getEnv("UI_PATH", "/app/ui/build"),
160+
ConfigDir: getEnv("CONFIG_DIR", "/app/config"),
161+
CheckInterval: checkInterval,
150162
GenerateInterval: generateInterval,
151-
Debug: debug,
152-
AllowCORS: allowCORS,
153-
CORSOrigin: getEnv("CORS_ORIGIN", ""),
163+
Debug: debug,
164+
AllowCORS: allowCORS,
165+
CORSOrigin: getEnv("CORS_ORIGIN", ""),
154166
}
155167
}
156168

models/datasource.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package models
2+
3+
import "time"
4+
5+
// DataSourceType represents the type of data source
6+
type DataSourceType string
7+
8+
const (
9+
PangolinAPI DataSourceType = "pangolin"
10+
TraefikAPI DataSourceType = "traefik"
11+
)
12+
13+
// DataSourceConfig represents configuration for a data source
14+
type DataSourceConfig struct {
15+
Type DataSourceType `json:"type"`
16+
URL string `json:"url"`
17+
BasicAuth struct {
18+
Username string `json:"username"`
19+
Password string `json:"password"`
20+
} `json:"basic_auth,omitempty"`
21+
}
22+
23+
// SystemConfig represents the overall system configuration
24+
type SystemConfig struct {
25+
ActiveDataSource string `json:"active_data_source"`
26+
DataSources map[string]DataSourceConfig `json:"data_sources"`
27+
}
28+
29+
// TraefikRouter represents a router configuration from Traefik API
30+
type TraefikRouter struct {
31+
EntryPoints []string `json:"entryPoints"`
32+
Middlewares []string `json:"middlewares"`
33+
Service string `json:"service"`
34+
Rule string `json:"rule"`
35+
Priority int `json:"priority"`
36+
TLS TraefikTLSConfig `json:"tls"`
37+
Status string `json:"status"`
38+
Name string `json:"name"`
39+
Provider string `json:"provider"`
40+
}
41+
42+
// TraefikTLSConfig represents TLS configuration in Traefik
43+
type TraefikTLSConfig struct {
44+
CertResolver string `json:"certResolver"`
45+
Domains []TraefikTLSDomain `json:"domains"`
46+
}
47+
48+
// TraefikTLSDomain represents a domain in Traefik TLS config
49+
type TraefikTLSDomain struct {
50+
Main string `json:"main"`
51+
Sans []string `json:"sans"`
52+
}
53+
54+
// ResourceCollection represents a collection of resources
55+
type ResourceCollection struct {
56+
Resources []Resource `json:"resources"`
57+
}
58+
59+
// Resource extends the existing resource model with source type
60+
type Resource struct {
61+
ID string `json:"id"`
62+
Host string `json:"host"`
63+
ServiceID string `json:"service_id"`
64+
OrgID string `json:"org_id"`
65+
SiteID string `json:"site_id"`
66+
Status string `json:"status"`
67+
SourceType string `json:"source_type"`
68+
Entrypoints string `json:"entrypoints"`
69+
TLSDomains string `json:"tls_domains"`
70+
TCPEnabled bool `json:"tcp_enabled"`
71+
TCPEntrypoints string `json:"tcp_entrypoints"`
72+
TCPSNIRule string `json:"tcp_sni_rule"`
73+
CustomHeaders string `json:"custom_headers"`
74+
RouterPriority int `json:"router_priority"`
75+
CreatedAt time.Time `json:"created_at"`
76+
UpdatedAt time.Time `json:"updated_at"`
77+
Middlewares string `json:"middlewares,omitempty"`
78+
}

0 commit comments

Comments
 (0)