85 lines
2.5 KiB
Go
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()
|
|
}
|