mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-02 04:20:50 +08:00
feat(server): Add cloud deploy mode
This commit is contained in:
@@ -96,6 +96,14 @@ func main() {
|
||||
var err error
|
||||
var cfg *config.Config
|
||||
var wd string
|
||||
var isCloudDeploy bool
|
||||
|
||||
// Check for cloud deploy mode only on first execution
|
||||
// Read env var name in uppercase: DEPLOY
|
||||
deployEnv := os.Getenv("DEPLOY")
|
||||
if deployEnv == "cloud" {
|
||||
isCloudDeploy = true
|
||||
}
|
||||
|
||||
// Determine and load the configuration file.
|
||||
// If a config path is provided via flags, it is used directly.
|
||||
@@ -103,18 +111,31 @@ func main() {
|
||||
var configFilePath string
|
||||
if configPath != "" {
|
||||
configFilePath = configPath
|
||||
cfg, err = config.LoadConfig(configPath)
|
||||
cfg, err = config.LoadConfigOptional(configPath, isCloudDeploy)
|
||||
} else {
|
||||
wd, err = os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get working directory: %v", err)
|
||||
}
|
||||
configFilePath = filepath.Join(wd, "config.yaml")
|
||||
cfg, err = config.LoadConfig(configFilePath)
|
||||
cfg, err = config.LoadConfigOptional(configFilePath, isCloudDeploy)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("failed to load config: %v", err)
|
||||
}
|
||||
|
||||
// Log if we're running without a config file in cloud deploy mode
|
||||
var configFileExists bool
|
||||
if isCloudDeploy {
|
||||
if _, err = os.Stat(configFilePath); os.IsNotExist(err) {
|
||||
// Don't mislead: API server will not start until configuration is provided.
|
||||
log.Info("Cloud deploy mode: No configuration file detected; standing by for configuration (API server not started)")
|
||||
configFileExists = false
|
||||
} else {
|
||||
log.Info("Cloud deploy mode: Configuration file detected; starting service")
|
||||
configFileExists = true
|
||||
}
|
||||
}
|
||||
usage.SetStatisticsEnabled(cfg.UsageStatisticsEnabled)
|
||||
|
||||
if err = logging.ConfigureLogOutput(cfg.LoggingToFile); err != nil {
|
||||
@@ -161,6 +182,12 @@ func main() {
|
||||
} else if geminiWebAuth {
|
||||
cmd.DoGeminiWebAuth(cfg)
|
||||
} else {
|
||||
// In cloud deploy mode without config file, just wait for shutdown signals
|
||||
if isCloudDeploy && !configFileExists {
|
||||
// No config file available, just wait for shutdown
|
||||
cmd.WaitForCloudDeploy()
|
||||
return
|
||||
}
|
||||
// Start the main proxy service
|
||||
cmd.StartService(cfg, configFilePath, password)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ services:
|
||||
COMMIT: ${COMMIT:-none}
|
||||
BUILD_DATE: ${BUILD_DATE:-unknown}
|
||||
container_name: cli-proxy-api
|
||||
environment:
|
||||
DEPLOY: ${DEPLOY:-}
|
||||
ports:
|
||||
- "8317:8317"
|
||||
- "8085:8085"
|
||||
|
||||
@@ -53,3 +53,17 @@ func StartService(cfg *config.Config, configPath string, localPassword string) {
|
||||
log.Fatalf("proxy service exited with error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCloudDeploy waits indefinitely for shutdown signals in cloud deploy mode
|
||||
// when no configuration file is available.
|
||||
func WaitForCloudDeploy() {
|
||||
// Clarify that we are intentionally idle for configuration and not running the API server.
|
||||
log.Info("Cloud deploy mode: No config found; standing by for configuration. API server is not started. Press Ctrl+C to exit.")
|
||||
|
||||
ctxSignal, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||
defer cancel()
|
||||
|
||||
// Block until shutdown signal is received
|
||||
<-ctxSignal.Done()
|
||||
log.Info("Cloud deploy mode: Shutdown signal received; exiting")
|
||||
}
|
||||
|
||||
@@ -187,9 +187,19 @@ type OpenAICompatibilityModel struct {
|
||||
// - *Config: The loaded configuration
|
||||
// - error: An error if the configuration could not be loaded
|
||||
func LoadConfig(configFile string) (*Config, error) {
|
||||
return LoadConfigOptional(configFile, false)
|
||||
}
|
||||
|
||||
// LoadConfigOptional reads YAML from configFile.
|
||||
// If optional is true and the file is missing, it returns an empty Config.
|
||||
func LoadConfigOptional(configFile string, optional bool) (*Config, error) {
|
||||
// Read the entire configuration file into memory.
|
||||
data, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
if optional && os.IsNotExist(err) {
|
||||
// Missing and optional: return empty config.
|
||||
return &Config{}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to read config file: %w", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user