Files
go-sip/internal/config/runtime.go
T

85 lines
2.5 KiB
Go

package config
import (
"errors"
"fmt"
"net"
"net/url"
"os"
"strings"
"git.ipao.vip/rogee/go-sip/internal/tenant"
)
// DispatcherEnvironment contains only deployment-owned startup values. The
// SaaS read secret is never a task/AI setting and must not be logged.
type DispatcherEnvironment struct {
DispatcherID string
SecretKey string
SaaSBaseURL string
RabbitMQURL string
SQLitePath string
}
// LoadDispatcherEnvironment is pure inspection: it opens no database, queue or
// network connection. The current executable accepts only isolated Mock mode.
func LoadDispatcherEnvironment(mode string) (DispatcherEnvironment, error) {
if mode != "mock" {
return DispatcherEnvironment{}, errors.New("Dispatcher accepts only isolated Mock mode")
}
get := func(name string) (string, error) {
value := os.Getenv(name)
if strings.TrimSpace(value) == "" {
return "", fmt.Errorf("%s is required", name)
}
return value, nil
}
var settings DispatcherEnvironment
var err error
if settings.DispatcherID, err = get("DISPATCHER_ID"); err != nil {
return DispatcherEnvironment{}, err
}
if tenant.ValidateDispatcherID(settings.DispatcherID) != nil {
return DispatcherEnvironment{}, errors.New("DISPATCHER_ID must be a canonical UUID v4")
}
if settings.SecretKey, err = get("DISPATCHER_SECRET_KEY"); err != nil {
return DispatcherEnvironment{}, err
}
if settings.SaaSBaseURL, err = get("SAAS_BASE_URL"); err != nil {
return DispatcherEnvironment{}, err
}
if !localEndpoint(settings.SaaSBaseURL, "http", "https") {
return DispatcherEnvironment{}, errors.New("SAAS_BASE_URL must name a local Mock HTTP endpoint")
}
if settings.RabbitMQURL, err = get("RABBITMQ_URL"); err != nil {
return DispatcherEnvironment{}, err
}
if !localEndpoint(settings.RabbitMQURL, "amqp", "amqps") {
return DispatcherEnvironment{}, errors.New("RABBITMQ_URL must name a local Mock AMQP endpoint")
}
if settings.SQLitePath, err = get("DISPATCHER_SQLITE_PATH"); err != nil {
return DispatcherEnvironment{}, err
}
return settings, nil
}
func localEndpoint(raw string, schemes ...string) bool {
parsed, err := url.Parse(raw)
if err != nil || parsed.Hostname() == "" || parsed.Opaque != "" || parsed.Fragment != "" || parsed.RawQuery != "" {
return false
}
validScheme := false
for _, scheme := range schemes {
validScheme = validScheme || parsed.Scheme == scheme
}
if !validScheme {
return false
}
host := parsed.Hostname()
if strings.EqualFold(host, "localhost") {
return true
}
ip := net.ParseIP(host)
return ip != nil && ip.IsLoopback()
}