CI / CI (pull_request) Successful in 4m38s
config.go: - Environment enum (dev/staging/prod) with auto-detect - MemoryServiceConfig + LLMConfig structs - Validate(): TLS pair check, file existence, prod LLM key requirement - In-cluster default host detection via KUBERNETES_SERVICE_HOST - TaskQueue + WorkerCount from env config_test.go: 11 tests - defaults, env override, TLS mismatch, TLS file not found - prod validation (requires LLM key), env parsing - in-cluster detection, port defaults, int parsing k8s/secrets.enc.yaml: SOPS-encrypted Secret - anthropic-api-key, memory-service-jwt, temporal-postgres-password - Age-encrypted, KSOPS-compatible Build: clean, full test suite passes
144 lines
4.1 KiB
Go
144 lines
4.1 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func clearEnv(t *testing.T) {
|
|
t.Helper()
|
|
for _, key := range []string{
|
|
"APP_ENV", "TEMPORAL_HOSTPORT", "TEMPORAL_NAMESPACE",
|
|
"TEMPORAL_TLS_CERT", "TEMPORAL_TLS_KEY", "TEMPORAL_TASK_QUEUE",
|
|
"TEMPORAL_WORKER_COUNT", "MEMORY_SERVICE_URL", "MEMORY_SERVICE_JWT_TOKEN",
|
|
"LOCAL_LLM_BASE_URL", "ANTHROPIC_API_KEY", "LLM_AUTH_TOKEN",
|
|
"LOG_LEVEL", "KUBERNETES_SERVICE_HOST",
|
|
} {
|
|
os.Unsetenv(key)
|
|
}
|
|
}
|
|
|
|
func TestLoadConfigDefaults(t *testing.T) {
|
|
clearEnv(t)
|
|
cfg, err := LoadConfig()
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, EnvDev, cfg.Env)
|
|
assert.Equal(t, "127.0.0.1:7233", cfg.Temporal.HostPort)
|
|
assert.Equal(t, "poimen-harness", cfg.Temporal.Namespace)
|
|
assert.Equal(t, "poimen-taskqueue", cfg.Temporal.TaskQueue)
|
|
assert.Equal(t, 10, cfg.Temporal.WorkerCount)
|
|
assert.Equal(t, "info", cfg.LogLevel)
|
|
}
|
|
|
|
func TestLoadConfigFromEnv(t *testing.T) {
|
|
clearEnv(t)
|
|
os.Setenv("APP_ENV", "staging")
|
|
os.Setenv("TEMPORAL_HOSTPORT", "temporal:7233")
|
|
os.Setenv("TEMPORAL_NAMESPACE", "test-ns")
|
|
os.Setenv("TEMPORAL_TASK_QUEUE", "test-queue")
|
|
os.Setenv("TEMPORAL_WORKER_COUNT", "5")
|
|
os.Setenv("MEMORY_SERVICE_URL", "http://memory:8080")
|
|
os.Setenv("ANTHROPIC_API_KEY", "sk-test")
|
|
os.Setenv("LOG_LEVEL", "debug")
|
|
|
|
cfg, err := LoadConfig()
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, EnvStaging, cfg.Env)
|
|
assert.Equal(t, "temporal:7233", cfg.Temporal.HostPort)
|
|
assert.Equal(t, "test-ns", cfg.Temporal.Namespace)
|
|
assert.Equal(t, "test-queue", cfg.Temporal.TaskQueue)
|
|
assert.Equal(t, 5, cfg.Temporal.WorkerCount)
|
|
assert.Equal(t, "http://memory:8080", cfg.MemoryService.URL)
|
|
assert.Equal(t, "sk-test", cfg.LLM.AnthropicKey)
|
|
assert.Equal(t, "debug", cfg.LogLevel)
|
|
}
|
|
|
|
func TestValidateTLSMismatch(t *testing.T) {
|
|
clearEnv(t)
|
|
os.Setenv("TEMPORAL_TLS_CERT", "/tmp/cert.pem")
|
|
// Missing TLS_KEY
|
|
|
|
_, err := LoadConfig()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "TEMPORAL_TLS_CERT and TEMPORAL_TLS_KEY must both be set")
|
|
}
|
|
|
|
func TestValidateTLSFileNotFound(t *testing.T) {
|
|
clearEnv(t)
|
|
os.Setenv("TEMPORAL_TLS_CERT", "/nonexistent/cert.pem")
|
|
os.Setenv("TEMPORAL_TLS_KEY", "/nonexistent/key.pem")
|
|
|
|
_, err := LoadConfig()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not found")
|
|
}
|
|
|
|
func TestValidateProdRequiresLLMKey(t *testing.T) {
|
|
clearEnv(t)
|
|
os.Setenv("APP_ENV", "prod")
|
|
|
|
_, err := LoadConfig()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "prod requires ANTHROPIC_API_KEY or LLM_AUTH_TOKEN")
|
|
}
|
|
|
|
func TestValidateProdWithAnthropicKey(t *testing.T) {
|
|
clearEnv(t)
|
|
os.Setenv("APP_ENV", "prod")
|
|
os.Setenv("ANTHROPIC_API_KEY", "sk-prod")
|
|
|
|
cfg, err := LoadConfig()
|
|
require.NoError(t, err)
|
|
assert.True(t, cfg.IsProd())
|
|
assert.False(t, cfg.IsDevOrStaging())
|
|
}
|
|
|
|
func TestValidateProdWithAuthToken(t *testing.T) {
|
|
clearEnv(t)
|
|
os.Setenv("APP_ENV", "prod")
|
|
os.Setenv("LLM_AUTH_TOKEN", "token-prod")
|
|
|
|
cfg, err := LoadConfig()
|
|
require.NoError(t, err)
|
|
assert.True(t, cfg.IsProd())
|
|
}
|
|
|
|
func TestParseEnv(t *testing.T) {
|
|
assert.Equal(t, EnvDev, parseEnv("dev"))
|
|
assert.Equal(t, EnvDev, parseEnv("unknown"))
|
|
assert.Equal(t, EnvStaging, parseEnv("staging"))
|
|
assert.Equal(t, EnvStaging, parseEnv("stage"))
|
|
assert.Equal(t, EnvProd, parseEnv("prod"))
|
|
assert.Equal(t, EnvProd, parseEnv("production"))
|
|
}
|
|
|
|
func TestDefaultTemporalHostInCluster(t *testing.T) {
|
|
clearEnv(t)
|
|
os.Setenv("KUBERNETES_SERVICE_HOST", "10.0.0.1")
|
|
|
|
cfg, err := LoadConfig()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "temporal-frontend.temporal.svc.cluster.local:7233", cfg.Temporal.HostPort)
|
|
}
|
|
|
|
func TestAddDefaultPort(t *testing.T) {
|
|
assert.Equal(t, "host:7233", addDefaultPort("host"))
|
|
assert.Equal(t, "host:9090", addDefaultPort("host:9090"))
|
|
}
|
|
|
|
func TestGetEnvIntOrDefault(t *testing.T) {
|
|
clearEnv(t)
|
|
assert.Equal(t, 10, getEnvIntOrDefault("TEMPORAL_WORKER_COUNT", 10))
|
|
|
|
os.Setenv("TEMPORAL_WORKER_COUNT", "abc")
|
|
assert.Equal(t, 10, getEnvIntOrDefault("TEMPORAL_WORKER_COUNT", 10))
|
|
|
|
os.Setenv("TEMPORAL_WORKER_COUNT", "20")
|
|
assert.Equal(t, 20, getEnvIntOrDefault("TEMPORAL_WORKER_COUNT", 10))
|
|
}
|