// Изменено: 2026-03-19 // Конфигурация сервиса — читается из env переменных при старте. // Все компоненты (API, builder, runner) получают конфиг через эту структуру. // Используем env а не файлы конфигурации — стандарт для k8s (ConfigMap/Secret → env). package config import ( "fmt" "os" "strconv" ) // Config — централизованная конфигурация всего сервиса. type Config struct { // APIPort — порт на котором слушает REST API сервер (default: 8080) APIPort int // PostgreSQL — параметры подключения к БД для хранения логов вызовов PostgresDSN string // S3 — параметры подключения к Ceph S3 для хранения кода функций S3Endpoint string S3AccessKey string S3SecretKey string S3Bucket string S3UseSSL bool // Registry — куда пушим собранные образы функций (DockerHub: "naeel", приватный: "host:port/prefix") RegistryHost string // RegistrySecret — имя k8s Secret типа kubernetes.io/dockerconfigjson // Монтируется в kaniko Job для авторизации в registry. // Создаётся через hack/create-registry-secret.sh RegistrySecret string // BuilderImage — образ для сборки функций (kaniko или buildah) BuilderImage string // IngressHost — базовый домен для HTTP триггеров (используется только // если ExternalURL не задан, для обратной совместимости). IngressHost string // ExternalURL — публичный URL API сервера, например: https://sless-api.kube5s.ru // Если задан, URL функции формируется как: {ExternalURL}/fn/{namespace}/{name} // Это позволяет обойтись без wildcard DNS *.fn. ExternalURL string // APIToken — статический Bearer-токен (legacy, не используется после перехода на JWT). // Поле сохранено для совместимости конфигурации. // Аутентификация происходит в middleware/auth.go через validateJWT(). APIToken string // Harbor — креды для Harbor API (создание проектов до push образов). // REGISTRY_HOST уже содержит адрес реестра — дублировать не нужно. // Если не заданы, EnsureProject пропускается (только DockerHub/без проектов). HarborUser string HarborPass string // RabbitMQURL — AMQP URL брокера для event-dispatcher. // Формат: amqp://user:pass@host:5672/ // Опционально — если не задан, event-триггеры не будут обрабатываться. RabbitMQURL string } func Load() (*Config, error) { cfg := &Config{ APIPort: 8080, S3UseSSL: false, BuilderImage: "gcr.io/kaniko-project/executor:latest", } // Опциональный порт API if v := os.Getenv("API_PORT"); v != "" { port, err := strconv.Atoi(v) if err != nil { return nil, fmt.Errorf("API_PORT must be a number: %w", err) } cfg.APIPort = port } // Обязательные параметры PostgreSQL cfg.PostgresDSN = os.Getenv("POSTGRES_DSN") if cfg.PostgresDSN == "" { return nil, fmt.Errorf("POSTGRES_DSN is required") } // Обязательные параметры S3 cfg.S3Endpoint = os.Getenv("S3_ENDPOINT") if cfg.S3Endpoint == "" { return nil, fmt.Errorf("S3_ENDPOINT is required") } cfg.S3AccessKey = os.Getenv("S3_ACCESS_KEY") if cfg.S3AccessKey == "" { return nil, fmt.Errorf("S3_ACCESS_KEY is required") } cfg.S3SecretKey = os.Getenv("S3_SECRET_KEY") if cfg.S3SecretKey == "" { return nil, fmt.Errorf("S3_SECRET_KEY is required") } cfg.S3Bucket = os.Getenv("S3_BUCKET") if cfg.S3Bucket == "" { // Используем дефолтный бакет если не задан cfg.S3Bucket = "sless-functions" } if v := os.Getenv("S3_USE_SSL"); v == "true" { cfg.S3UseSSL = true } // Обязательный адрес registry cfg.RegistryHost = os.Getenv("REGISTRY_HOST") if cfg.RegistryHost == "" { return nil, fmt.Errorf("REGISTRY_HOST is required") } // Secret с docker-кредами для kaniko (опционально — без него push в приватный registry упадёт) cfg.RegistrySecret = os.Getenv("REGISTRY_SECRET") if cfg.RegistrySecret == "" { cfg.RegistrySecret = "sless-registry-auth" } // Опциональные параметры с дефолтами if v := os.Getenv("BUILDER_IMAGE"); v != "" { cfg.BuilderImage = v } // IngressHost — базовый домен для HTTP триггеров (fallback) cfg.IngressHost = os.Getenv("INGRESS_HOST") if cfg.IngressHost == "" { cfg.IngressHost = "fn.kube5s.ru" } // ExternalURL — публичный URL сервиса для формирования URL функций cfg.ExternalURL = os.Getenv("EXTERNAL_URL") // APIToken — legacy поле, JWT от nubes читается напрямую из Authorization заголовка. // Не required: auth middleware использует validateJWT, а не статический токен. cfg.APIToken = os.Getenv("SLESS_API_TOKEN") // Harbor API креды — опциональны. // Если не заданы, EnsureProject пропускается (push работает через docker-кред в канiko). cfg.HarborUser = os.Getenv("HARBOR_USER") cfg.HarborPass = os.Getenv("HARBOR_PASS") // RabbitMQ — опционально. Нужен только если используются event-триггеры. cfg.RabbitMQURL = os.Getenv("RABBITMQ_URL") return cfg, nil }