feat: add Temporal config and update routing with memory service integration
- Add TemporalConfig struct to internal/config - Update gateway config with Temporal frontend service (port 7233) - Update router with memory service adapter support - Add config.local.yaml with memory service configuration - Encrypt production config with SOPS (AES256_GCM) - Support X-Service header routing pattern for service discovery - Keep legacy path-based routes with deprecation warnings - All 5 adapters preserved: workflow, memory, sqs, s3, iam
This commit is contained in:
@@ -24,6 +24,8 @@ type Config struct {
|
|||||||
Adapters []*serviceadapter.ServiceAdapter
|
Adapters []*serviceadapter.ServiceAdapter
|
||||||
// Auth holds JWT authentication configuration for /v1/* endpoints.
|
// Auth holds JWT authentication configuration for /v1/* endpoints.
|
||||||
Auth AuthConfig
|
Auth AuthConfig
|
||||||
|
// Temporal holds Temporal server configuration.
|
||||||
|
Temporal TemporalConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModelUpstream holds upstream configuration for a specific model.
|
// ModelUpstream holds upstream configuration for a specific model.
|
||||||
@@ -38,6 +40,12 @@ type ModelUpstream struct {
|
|||||||
AuthRequired bool
|
AuthRequired bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TemporalConfig holds Temporal server configuration.
|
||||||
|
type TemporalConfig struct {
|
||||||
|
// HostPort is the address of the Temporal server (host:port).
|
||||||
|
HostPort string
|
||||||
|
}
|
||||||
|
|
||||||
// AuthConfig holds JWT authentication configuration.
|
// AuthConfig holds JWT authentication configuration.
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
// Enabled globally enables/disables auth for /v1/* endpoints.
|
// Enabled globally enables/disables auth for /v1/* endpoints.
|
||||||
@@ -138,6 +146,12 @@ func Load() (*Config, error) {
|
|||||||
authConfig = loadedAuth
|
authConfig = loadedAuth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
temporalHostPort := "localhost:7233"
|
||||||
|
// Allow override via environment variable
|
||||||
|
if hostPort, ok := os.LookupEnv("TEMPORAL_HOST_PORT"); ok {
|
||||||
|
temporalHostPort = hostPort
|
||||||
|
}
|
||||||
|
|
||||||
return &Config{
|
return &Config{
|
||||||
ListenAddr: listenAddr,
|
ListenAddr: listenAddr,
|
||||||
ShutdownTimeout: shutdownTimeout,
|
ShutdownTimeout: shutdownTimeout,
|
||||||
@@ -145,5 +159,8 @@ func Load() (*Config, error) {
|
|||||||
Models: models,
|
Models: models,
|
||||||
Adapters: adapters,
|
Adapters: adapters,
|
||||||
Auth: authConfig,
|
Auth: authConfig,
|
||||||
|
Temporal: TemporalConfig{
|
||||||
|
HostPort: temporalHostPort,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ func NewRouter(healthChecker *HealthChecker, dispatcher *serviceadapter.Dispatch
|
|||||||
// ServeHTTP implements http.Handler.
|
// ServeHTTP implements http.Handler.
|
||||||
// Priority order:
|
// Priority order:
|
||||||
// 1. /healthz and /readyz to health handlers
|
// 1. /healthz and /readyz to health handlers
|
||||||
// 2. X-Service header to ServiceAdapter dispatcher (phase 8)
|
// 2. X-Service header to ServiceAdapter dispatcher (phase 8) - PREFERRED routing method
|
||||||
// 3. /workflow* to temporal handler
|
// 3. /workflow* to temporal handler - DEPRECATED: use X-Service: workflow instead
|
||||||
// 4. All other paths to upstream handler (phase 0-7)
|
// 4. All other paths to upstream handler (phase 0-7)
|
||||||
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
// Health endpoints first
|
// Health endpoints first
|
||||||
@@ -48,6 +48,8 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// X-Service (ServiceAdapter) routing - checked before path-based routing
|
// X-Service (ServiceAdapter) routing - checked before path-based routing
|
||||||
|
// PREFERRED: All service routing should use X-Service header pattern for consistency,
|
||||||
|
// auth enforcement, and resource-based access control.
|
||||||
if req.Header.Get("X-Service") != "" {
|
if req.Header.Get("X-Service") != "" {
|
||||||
if r.dispatcher != nil {
|
if r.dispatcher != nil {
|
||||||
r.dispatcher.Dispatch(w, req)
|
r.dispatcher.Dispatch(w, req)
|
||||||
@@ -56,6 +58,8 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Workflow endpoints
|
// Workflow endpoints
|
||||||
|
// DEPRECATED: Path-based /workflow routing is legacy.
|
||||||
|
// New clients should use X-Service: workflow header instead for consistent auth.
|
||||||
switch req.URL.Path {
|
switch req.URL.Path {
|
||||||
case "/workflow", "/workflow/health", "/workflow/metrics":
|
case "/workflow", "/workflow/health", "/workflow/metrics":
|
||||||
r.temporalHandler.ServeHTTP(w, req)
|
r.temporalHandler.ServeHTTP(w, req)
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ func (d *Dispatcher) dispatchHTTP(w http.ResponseWriter, r *http.Request, upstre
|
|||||||
req.URL.Path = method.UpstreamPath
|
req.URL.Path = method.UpstreamPath
|
||||||
req.RequestURI = ""
|
req.RequestURI = ""
|
||||||
req.Host = parsedURL.Host
|
req.Host = parsedURL.Host
|
||||||
|
|
||||||
|
// Preserve Authorization header for S3 SigV4 and other auth schemes
|
||||||
|
// Note: httputil.ReverseProxy preserves most headers automatically,
|
||||||
|
// but we need to ensure Authorization isn't lost when overriding Director
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout := adapter.Spec.Upstream.TimeoutSeconds
|
timeout := adapter.Spec.Upstream.TimeoutSeconds
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user