ParseConfigBytes parses a YAML configuration payload into Config and applies the same in-memory normalizations as LoadConfigOptional, without persisting any changes to disk.
(data []byte)
| 12 | // ParseConfigBytes parses a YAML configuration payload into Config and applies the same |
| 13 | // in-memory normalizations as LoadConfigOptional, without persisting any changes to disk. |
| 14 | func ParseConfigBytes(data []byte) (*Config, error) { |
| 15 | if len(data) == 0 { |
| 16 | return nil, fmt.Errorf("config payload is empty") |
| 17 | } |
| 18 | |
| 19 | var cfg Config |
| 20 | // Keep defaults aligned with LoadConfigOptional. |
| 21 | cfg.Host = "" // Default empty: binds to all interfaces (IPv4 + IPv6) |
| 22 | cfg.LoggingToFile = false |
| 23 | cfg.LogsMaxTotalSizeMB = 0 |
| 24 | cfg.ErrorLogsMaxFiles = 10 |
| 25 | cfg.UsageStatisticsEnabled = false |
| 26 | cfg.RedisUsageQueueRetentionSeconds = 60 |
| 27 | cfg.DisableCooling = false |
| 28 | cfg.SaveCooldownStatus = false |
| 29 | cfg.TransientErrorCooldownSeconds = 0 |
| 30 | cfg.DisableImageGeneration = DisableImageGenerationOff |
| 31 | cfg.Pprof.Enable = false |
| 32 | cfg.Pprof.Addr = DefaultPprofAddr |
| 33 | cfg.RemoteManagement.PanelGitHubRepository = DefaultPanelGitHubRepository |
| 34 | |
| 35 | if err := yaml.Unmarshal(data, &cfg); err != nil { |
| 36 | return nil, fmt.Errorf("parse config payload: %w", err) |
| 37 | } |
| 38 | |
| 39 | // Hash remote management key if plaintext is detected (nested), but do NOT persist. |
| 40 | if cfg.RemoteManagement.SecretKey != "" && !looksLikeBcrypt(cfg.RemoteManagement.SecretKey) { |
| 41 | hashed, errHash := bcrypt.GenerateFromPassword([]byte(cfg.RemoteManagement.SecretKey), bcrypt.DefaultCost) |
| 42 | if errHash != nil { |
| 43 | return nil, fmt.Errorf("hash remote management key: %w", errHash) |
| 44 | } |
| 45 | cfg.RemoteManagement.SecretKey = string(hashed) |
| 46 | } |
| 47 | |
| 48 | cfg.RemoteManagement.PanelGitHubRepository = strings.TrimSpace(cfg.RemoteManagement.PanelGitHubRepository) |
| 49 | if cfg.RemoteManagement.PanelGitHubRepository == "" { |
| 50 | cfg.RemoteManagement.PanelGitHubRepository = DefaultPanelGitHubRepository |
| 51 | } |
| 52 | |
| 53 | cfg.Pprof.Addr = strings.TrimSpace(cfg.Pprof.Addr) |
| 54 | if cfg.Pprof.Addr == "" { |
| 55 | cfg.Pprof.Addr = DefaultPprofAddr |
| 56 | } |
| 57 | |
| 58 | if cfg.LogsMaxTotalSizeMB < 0 { |
| 59 | cfg.LogsMaxTotalSizeMB = 0 |
| 60 | } |
| 61 | |
| 62 | if cfg.ErrorLogsMaxFiles < 0 { |
| 63 | cfg.ErrorLogsMaxFiles = 10 |
| 64 | } |
| 65 | |
| 66 | if cfg.RedisUsageQueueRetentionSeconds <= 0 { |
| 67 | cfg.RedisUsageQueueRetentionSeconds = 60 |
| 68 | } else if cfg.RedisUsageQueueRetentionSeconds > 3600 { |
| 69 | log.WithField("value", cfg.RedisUsageQueueRetentionSeconds).Warn("redis-usage-queue-retention-seconds too large; clamping to 3600") |
| 70 | cfg.RedisUsageQueueRetentionSeconds = 3600 |
| 71 | } |