143 lines
3.6 KiB
Go
143 lines
3.6 KiB
Go
package config
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
const defaultAddr = ":8080"
|
|
const defaultDataDir = ".platform-data"
|
|
const defaultStorageBackend = "file"
|
|
|
|
type Config struct {
|
|
Addr string
|
|
StorageBackend string
|
|
MySQLDSN string
|
|
DataDir string
|
|
MetadataPath string
|
|
LogDir string
|
|
ArtifactDir string
|
|
LogBodyBackend string
|
|
BootstrapAdminEmail string
|
|
BootstrapAdminPassword string
|
|
SecretEnvelopeKey string
|
|
}
|
|
|
|
func Load() Config {
|
|
loadLocalEnvFiles()
|
|
|
|
addr := os.Getenv("PLATFORM_ADDR")
|
|
if addr == "" {
|
|
addr = defaultAddr
|
|
}
|
|
dataDir := strings.TrimSpace(os.Getenv("PLATFORM_DATA_DIR"))
|
|
if dataDir == "" {
|
|
dataDir = defaultDataDir
|
|
}
|
|
metadataPath := strings.TrimSpace(os.Getenv("PLATFORM_METADATA_PATH"))
|
|
if metadataPath == "" {
|
|
metadataPath = filepath.Join(dataDir, "metadata.json")
|
|
}
|
|
logDir := strings.TrimSpace(os.Getenv("PLATFORM_LOG_DIR"))
|
|
if logDir == "" {
|
|
logDir = filepath.Join(dataDir, "logs")
|
|
}
|
|
artifactDir := strings.TrimSpace(os.Getenv("PLATFORM_ARTIFACT_DIR"))
|
|
if artifactDir == "" {
|
|
artifactDir = filepath.Join(dataDir, "artifacts")
|
|
}
|
|
storageBackend := strings.TrimSpace(os.Getenv("PLATFORM_STORAGE_BACKEND"))
|
|
if storageBackend == "" {
|
|
storageBackend = defaultStorageBackend
|
|
}
|
|
logBodyBackend := strings.TrimSpace(os.Getenv("PLATFORM_LOG_BODY_BACKEND"))
|
|
|
|
return Config{
|
|
Addr: addr,
|
|
StorageBackend: storageBackend,
|
|
MySQLDSN: strings.TrimSpace(os.Getenv("PLATFORM_MYSQL_DSN")),
|
|
DataDir: dataDir,
|
|
MetadataPath: metadataPath,
|
|
LogDir: logDir,
|
|
ArtifactDir: artifactDir,
|
|
LogBodyBackend: logBodyBackend,
|
|
BootstrapAdminEmail: strings.TrimSpace(os.Getenv("PLATFORM_BOOTSTRAP_ADMIN_EMAIL")),
|
|
BootstrapAdminPassword: os.Getenv("PLATFORM_BOOTSTRAP_ADMIN_PASSWORD"),
|
|
SecretEnvelopeKey: os.Getenv("PLATFORM_SECRET_ENVELOPE_KEY"),
|
|
}
|
|
}
|
|
|
|
func loadLocalEnvFiles() {
|
|
candidates := []string{".env", filepath.Join("platform", ".env")}
|
|
for _, path := range candidates {
|
|
loadEnvFile(path)
|
|
}
|
|
}
|
|
|
|
func loadEnvFile(path string) {
|
|
file, err := os.Open(path)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
key, value, ok := parseEnvLine(scanner.Text())
|
|
if !ok {
|
|
continue
|
|
}
|
|
if _, exists := os.LookupEnv(key); exists {
|
|
continue
|
|
}
|
|
_ = os.Setenv(key, value)
|
|
}
|
|
}
|
|
|
|
func parseEnvLine(line string) (string, string, bool) {
|
|
line = strings.TrimSpace(line)
|
|
if line == "" || strings.HasPrefix(line, "#") {
|
|
return "", "", false
|
|
}
|
|
line = strings.TrimSpace(strings.TrimPrefix(line, "export "))
|
|
key, value, found := strings.Cut(line, "=")
|
|
if !found {
|
|
return "", "", false
|
|
}
|
|
key = strings.TrimSpace(key)
|
|
if key == "" || strings.ContainsAny(key, " \t") {
|
|
return "", "", false
|
|
}
|
|
value = strings.TrimSpace(stripInlineComment(strings.TrimSpace(value)))
|
|
if len(value) >= 2 {
|
|
if (value[0] == '"' && value[len(value)-1] == '"') || (value[0] == '\'' && value[len(value)-1] == '\'') {
|
|
value = value[1 : len(value)-1]
|
|
}
|
|
}
|
|
return key, value, true
|
|
}
|
|
|
|
func stripInlineComment(value string) string {
|
|
inSingleQuote := false
|
|
inDoubleQuote := false
|
|
for index, char := range value {
|
|
switch char {
|
|
case '\'':
|
|
if !inDoubleQuote {
|
|
inSingleQuote = !inSingleQuote
|
|
}
|
|
case '"':
|
|
if !inSingleQuote {
|
|
inDoubleQuote = !inDoubleQuote
|
|
}
|
|
case '#':
|
|
if !inSingleQuote && !inDoubleQuote && index > 0 && value[index-1] == ' ' {
|
|
return strings.TrimSpace(value[:index])
|
|
}
|
|
}
|
|
}
|
|
return value
|
|
}
|