Files
sless/internal/config/config.go
T
“Naeel” 2ee9cae6d2 feat: proxy /fn/{namespace}/{name} — обход wildcard DNS
Проблема: wildcard DNS *.fn.kube5s.ru недоступен.
Решение: прокси через sless-api.kube5s.ru/fn/{ns}/{name}.

- handler/invoke.go: прокси к Service функции внутри кластера
- router.go: /fn/ без auth токена, /v1/ с auth (gorilla Use())
- config.go: поле ExternalURL (EXTERNAL_URL env)
- trigger_controller.go: если ExternalURL задан — URL = ExternalURL/fn/{ns}/{fn}
  иначе fallback: Ingress + поддомен (прежнее поведение)
- operator.yaml: EXTERNAL_URL=https://sless-api.kube5s.ru, image v0.1.5

Оператор v0.1.5 задеплоен.
E2E: curl https://sless-api.kube5s.ru/fn/default/hello-node → {"message":"Hello, Naeel! (nodejs20)"}
2026-03-07 18:36:03 +04:00

142 lines
5.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Изменено: 2026-03-07
// Конфигурация сервиса — читается из 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
// FunctionNamespace — префикс namespace для функций пользователей.
// Итоговый namespace: FunctionNamespacePrefix + "-" + functionName
FunctionNamespacePrefix 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-токен для v1 REST API аутентификации.
// В prod заменить на вызов auth-сервиса.
APIToken string
}
// Load читает конфиг из env переменных.
// Возвращает ошибку если обязательные переменные не заданы.
func Load() (*Config, error) {
cfg := &Config{
APIPort: 8080,
S3UseSSL: false,
FunctionNamespacePrefix: "sless-fn",
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("FUNCTION_NAMESPACE_PREFIX"); v != "" {
cfg.FunctionNamespacePrefix = v
}
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 — обязательный токен для REST API
cfg.APIToken = os.Getenv("SLESS_API_TOKEN")
if cfg.APIToken == "" {
return nil, fmt.Errorf("SLESS_API_TOKEN is required")
}
return cfg, nil
}