GAL v1.3.0 - Implementierungsplan¶
Status: ✅ RELEASED - 2025-10-19 Focus: Import/Migration & Provider Portability Estimated Effort: 12 Wochen Actual Effort: 12 Wochen (100% on target)
🎯 Mission¶
Provider Lock-in brechen: Ermögliche Migration bestehender Gateway-Konfigurationen zu GAL und damit zu jedem anderen Provider.
Vision¶
Unternehmen mit bestehenden Gateway-Deployments (Nginx, HAProxy, Kong, etc.) können ihre Konfigurationen automatisch zu GAL konvertieren und damit: 1. Portabilität gewinnen - Wechsel zu anderem Provider in Minuten statt Wochen 2. Vendor Lock-in vermeiden - Nicht mehr an einen Provider gebunden 3. Multi-Provider nutzen - Gleiche Config auf verschiedenen Providern 4. Migration vereinfachen - Nginx → HAProxy, Kong → Envoy, etc.
📋 Feature Overview¶
| # | Feature | Priority | Status | Effort | Dependencies |
|---|---|---|---|---|---|
| 1 | Envoy Import (YAML Parser) | 🔴 High | ✅ Done | 1 Woche | - |
| 2 | Kong Import (YAML Parser) | 🔴 High | ✅ Done | 1 Woche | Feature 1 |
| 3 | APISIX Import (JSON/YAML Parser) | 🔴 High | ✅ Done | 1 Woche | Features 1-2 |
| 4 | Traefik Import (YAML Parser) | 🔴 High | ✅ Done | 1 Woche | Features 1-3 |
| 5 | Nginx Import (Custom Parser) | 🔴 High | ✅ Done | 2 Wochen | Features 1-4 |
| 6 | HAProxy Import (Custom Parser) | 🔴 High | ✅ Done | 2 Wochen | Features 1-5 |
| 7 | Compatibility Checker & Comparison | 🟡 Medium | ✅ Done | 2 Wochen | Features 1-6 |
| 8 | Migration Assistant (Interactive CLI) | 🟡 Medium | ✅ Done | 2 Wochen | Features 1-7 |
Total Estimated Effort: 12 Wochen Progress: 8/8 Features completed (100%) 🎉
Release Strategy: - v1.3.0-alpha1 (Week 2): Envoy + Kong Import ✅ COMPLETE - v1.3.0-alpha2 (Week 4): + APISIX + Traefik Import ✅ COMPLETE - v1.3.0-beta1 (Week 6): + Nginx Import ✅ COMPLETE - v1.3.0-beta2 (Week 8): + HAProxy Import ✅ COMPLETE - v1.3.0-rc1 (Week 10): + Compatibility Checker ✅ COMPLETE - v1.3.0 Final (Week 12): + Migration Assistant ✅ COMPLETE
🎯 Shared Infrastructure (All Features)¶
Provider Interface Extension¶
File: gal/provider.py
from abc import ABC, abstractmethod
from typing import List, Dict, Any
class Provider(ABC):
"""Abstract base class for all gateway providers."""
@abstractmethod
def parse(self, provider_config: str) -> Config:
"""Parse provider-specific config to GAL (NEU!)."""
pass
def get_import_warnings(self) -> List[str]:
"""Return warnings from last parse operation."""
return []
def get_import_report(self) -> Dict[str, Any]:
"""Return detailed import report."""
return {
"features_mapped": [],
"features_skipped": [],
"warnings": [],
"provider_specific": {}
}
CLI Command: gal import¶
# Import provider config to GAL
gal import --provider nginx --input nginx.conf --output gal-config.yaml
# Dry-run to preview
gal import --provider envoy --input envoy.yaml --dry-run
# With import report
gal import --provider haproxy --input haproxy.cfg --output gal.yaml --report import-report.json
Feature Mapping Matrix¶
| GAL Feature | Envoy | Kong | APISIX | Traefik | Nginx | HAProxy |
|---|---|---|---|---|---|---|
| Routing (path_prefix) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Methods (GET, POST) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Upstream (targets) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Load Balancing | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Rate Limiting | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Basic Auth | ⚠️ | ✅ | ✅ | ✅ | ✅ | ✅ |
| JWT Auth | ✅ | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
| Headers | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| CORS | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Health Checks | ✅ | ✅ | ✅ | ✅ | ⚠️ | ✅ |
📦 Feature 1: Envoy Import (YAML Parser)¶
Status: ✅ IMPLEMENTED | Effort: 1 Woche | Release: v1.3.0-alpha1 | Commits: 652a78d, 067c197
✅ Implementation Summary¶
Provider Implementation: gal/providers/envoy.py:1159-1381
class EnvoyProvider(Provider):
def parse(self, provider_config: str) -> Config:
"""Parse Envoy YAML configuration to GAL format.
Converts static_resources configuration into GAL Config model.
Extracts clusters, listeners, routes, health checks, and load balancing.
"""
envoy_config = yaml.safe_load(provider_config)
# Parse clusters → Services
services = []
cluster_map = {}
for cluster in clusters:
service = self._parse_cluster(cluster)
services.append(service)
cluster_map[cluster.get("name")] = service
# Parse listeners/routes
for listener in listeners:
self._parse_listener_routes(listener, cluster_map)
return Config(version="1.0", provider="envoy", services=services)
Helper Methods:
- _parse_cluster(): Cluster → Service conversion with targets, health checks, load balancing
- _map_envoy_lb_policy(): Maps Envoy LB policies to GAL algorithms
- _parse_listener_routes(): Extracts routes from HTTP connection manager
CLI Command: gal/gal-cli.py:225-368 (import-config)
Manager Extension: gal/manager.py:217-239 (get_provider())
Tests: tests/test_import_envoy.py - 15 tests, all passing ✅
- Basic Import (3 tests): Simple cluster, weighted targets, routes
- Health Checks (3 tests): Active, passive, combined
- Load Balancing (5 tests): All algorithms (ROUND_ROBIN, LEAST_REQUEST, RING_HASH, etc.)
- Multi-Service (1 test): Multiple clusters
- Error Handling (3 tests): Invalid YAML, empty config, no endpoints
Supported Features:
- ✅ Clusters → Services (name extraction: api_cluster → api)
- ✅ Load assignment endpoints → UpstreamTargets (with weights)
- ✅ Health checks → ActiveHealthCheck (HTTP probes with interval/timeout/thresholds)
- ✅ Outlier detection → PassiveHealthCheck (consecutive_5xx → max_failures)
- ✅ Load balancing policies → LoadBalancerConfig (all algorithms mapped)
- ✅ Listeners + route_config → Routes (path prefix extraction)
- ✅ Multiple clusters → Multiple services
Example:
# Input: envoy.yaml
static_resources:
clusters:
- name: api_cluster
lb_policy: ROUND_ROBIN
load_assignment:
endpoints:
- lb_endpoints:
- endpoint:
address: {socket_address: {address: api.internal, port_value: 8080}}
load_balancing_weight: {value: 2}
# Output: gal-config.yaml
services:
- name: api
type: rest
upstream:
targets:
- {host: api.internal, port: 8080, weight: 2}
load_balancer: {algorithm: round_robin}
routes:
- path_prefix: /api
Coverage: 16% (new parsing code covered by tests)
📖 Detail-Dokumentation: docs/import/envoy.md
📦 Feature 2: Kong Import (YAML/JSON Parser)¶
Status: ✅ IMPLEMENTED | Effort: 1 Woche | Release: v1.3.0-alpha1 | Commit: 93845e7
✅ Implementation Summary¶
Provider Implementation: gal/providers/kong.py:765-1210 (~470 lines, 15 helper methods)
class KongProvider(Provider):
def parse(self, provider_config: str) -> Config:
"""Parse Kong declarative config (YAML/JSON) to GAL format.
Supports Kong 3.0 declarative config with services, routes,
upstreams, targets, and plugins.
"""
# Try YAML first, then JSON
kong_config = yaml.safe_load(provider_config) or json.loads(provider_config)
# Create default global config (Kong proxy port 8000)
global_config = GlobalConfig(host="0.0.0.0", port=8000, timeout="60s")
return Config(
version="1.0",
provider="kong",
global_config=global_config,
services=self._parse_services(kong_config)
)
Helper Methods (15 methods):
Service & Upstream Parsing:
- _parse_services(): Orchestrates service parsing from Kong config
- _parse_service(): Converts Kong service → GAL Service (with type="rest", protocol="http")
- _parse_upstream(): Parses Kong upstream with targets and health checks
- _parse_targets(): Extracts UpstreamTarget list with weights
- _map_lb_algorithm(): Maps Kong LB algorithms to GAL
- round-robin → round_robin
- least-connections → least_conn
- consistent-hashing → ip_hash
- latency → least_conn
Health Checks:
- _parse_health_check(): Parses active + passive health checks
- Active: http_path, interval, timeout, healthy/unhealthy thresholds
- Passive: max_failures from unhealthy.http_failures
Route & Plugin Parsing:
- _parse_route(): Converts Kong routes with path/methods and applies plugins
Rate Limiting:
- _parse_rate_limiting_plugin(): Converts rate-limiting plugin config
- Supports: second, minute, hour, day, month, year
- Converts to requests_per_second (e.g., minute: 600 → 10 req/s)
- Maps limit_by to key_type (ip, header, consumer)
Authentication (with import warnings):
- _parse_key_auth_plugin(): API Key authentication
- Extracts key_names (defaults to "apikey")
- Sets in_location="header"
- ⚠️ Warning: API keys not imported for security
_parse_basic_auth_plugin(): Basic authentication- Creates BasicAuthConfig with empty users dict
-
⚠️ Warning: User credentials not imported for security
-
_parse_jwt_plugin(): JWT authentication - Maps algorithm to algorithms list
- Sets issuer/audience to "CONFIGURE_MANUALLY"
- ⚠️ Warning: JWT secrets not imported for security
Header Manipulation:
- _parse_request_transformer_plugin(): Request header add/remove
- Parses "Header:Value" format to dict
- _parse_response_transformer_plugin(): Response header add/remove
- _enrich_response_headers(): Merges response headers from multiple plugins
CORS:
- _parse_cors_plugin(): Parses CORS config
- origins, methods, headers, credentials, max_age
Utilities:
- get_import_warnings(): Returns list of import warnings for user review
CLI Command: gal-cli.py:225-368 (already implemented)
Tests: tests/test_import_kong.py - 21 tests, all passing ✅
Test Coverage: - TestKongImportBasic (3 tests): Simple service, service+route, JSON format - TestKongImportUpstream (2 tests): Targets with weights, all LB algorithms - TestKongImportHealthChecks (3 tests): Active, passive, combined - TestKongImportRateLimiting (2 tests): Second-based, minute-based (with conversion) - TestKongImportAuthentication (3 tests): Key-auth, basic-auth, JWT (all with warning checks) - TestKongImportHeaders (2 tests): Request transformer, response transformer - TestKongImportCORS (1 test): CORS plugin with all options - TestKongImportMultiService (1 test): 3 services with routes - TestKongImportErrors (3 tests): Invalid YAML, empty config, service without name - TestKongImportCombined (1 test): Production config with all features
Supported Features: - ✅ Services & Upstreams (URL parsing: http://host:port) - ✅ Targets with weights - ✅ Load Balancing (4 algorithms: round-robin, least-connections, consistent-hashing, latency) - ✅ Active Health Checks (http_path, interval, timeout, healthy/unhealthy thresholds) - ✅ Passive Health Checks (max_failures from traffic monitoring) - ✅ Rate Limiting (second/minute/hour/day conversion to req/s) - ✅ API Key Authentication (key_names extraction) - ✅ Basic Authentication (with security warning) - ✅ JWT Authentication (algorithm mapping, with security warning) - ✅ Request Header Transformation (add/remove with "Header:Value" parsing) - ✅ Response Header Transformation (add/remove) - ✅ CORS (origins, methods, headers, credentials, max_age) - ✅ Multiple Services & Routes - ✅ YAML & JSON format support
Import Warnings (Security): - ⚠️ API keys not imported (security) - user must configure manually - ⚠️ Basic auth user credentials not imported (security) - ⚠️ JWT secrets not imported (security) - issuer/audience set to "CONFIGURE_MANUALLY"
Example:
# Input: kong.yaml
_format_version: "3.0"
services:
- name: api_service
url: http://api_upstream
upstreams:
- name: api_upstream
algorithm: round-robin
healthchecks:
active:
http_path: /health
healthy: {interval: 10, successes: 2}
unhealthy: {http_failures: 3}
targets:
- upstream: api_upstream
target: api-1:8080
weight: 100
routes:
- name: api_route
service: api_service
paths: [/api/v1]
methods: [GET, POST]
plugins:
- name: rate-limiting
route: api_route
config: {second: 100, limit_by: ip}
- name: key-auth
route: api_route
config: {key_names: [apikey]}
- name: cors
route: api_route
config: {origins: ["https://app.example.com"], credentials: true}
# Output: gal-config.yaml (simplified)
services:
- name: api_service
type: rest
protocol: http
upstream:
targets:
- {host: api-1, port: 8080, weight: 100}
load_balancer: {algorithm: round_robin}
health_check:
active: {enabled: true, http_path: /health, interval: "10s", healthy_threshold: 2, unhealthy_threshold: 3}
routes:
- path_prefix: /api/v1
methods: [GET, POST]
rate_limit: {enabled: true, requests_per_second: 100, key_type: ip_address}
authentication: {enabled: true, type: api_key, api_key: {key_name: apikey}}
cors: {enabled: true, allowed_origins: ["https://app.example.com"], allow_credentials: true}
Coverage: kong.py: 8% → 37% (improved by 29%)
📖 Detail-Dokumentation: docs/import/kong.md
📦 Feature 3: APISIX Import (JSON/YAML Parser)¶
Status: ✅ IMPLEMENTED | Effort: 1 Woche | Release: v1.3.0-alpha2 | Commit: 4378d95
✅ Implementation Summary¶
Provider Implementation: gal/providers/apisix.py:904-1292 (~390 lines, 15 helper methods)
class APISIXProvider(Provider):
def parse(self, provider_config: str) -> Config:
"""Parse APISIX JSON/YAML configuration to GAL format.
APISIX supports both etcd and standalone (config file) mode.
This parser handles standalone config files.
"""
# Try YAML first, then JSON
apisix_config = yaml.safe_load(provider_config) or json.loads(provider_config)
# Create default global config (APISIX HTTP port 9080)
global_config = GlobalConfig(host="0.0.0.0", port=9080, timeout="60s")
return Config(
version="1.0",
provider="apisix",
global_config=global_config,
services=self._parse_services(apisix_config)
)
Helper Methods (15 methods):
Service & Upstream Parsing:
- _parse_services(): Orchestrates service parsing from APISIX config
- _parse_service(): Converts APISIX service → GAL Service (ID-based linking)
- _parse_upstream(): Parses APISIX upstream with nodes (dict format: {"host:port": weight})
- _map_lb_algorithm(): Maps APISIX LB algorithms to GAL
- roundrobin → round_robin
- chash (consistent hash) → ip_hash
- ewma (exponentially weighted moving average) → least_conn
- least_conn → least_conn
Health Checks:
- _parse_health_check(): Parses active + passive health checks
- Active: http_path, interval, timeout, healthy/unhealthy thresholds
- Passive: outlier detection monitoring
Route & Plugin Parsing:
- _parse_route(): Converts APISIX routes with URI and plugins
Rate Limiting (2 plugins):
- _parse_limit_req_plugin(): Leaky bucket rate limiting
- rate (requests per second), burst
- _parse_limit_count_plugin(): Fixed window rate limiting
- count/time_window → requests_per_second conversion
Authentication (with import warnings):
- _parse_key_auth_plugin(): API Key authentication (header-based)
- ⚠️ Warning: API keys not imported for security
- _parse_basic_auth_plugin(): Basic authentication
- ⚠️ Warning: User credentials not imported for security
- _parse_jwt_auth_plugin(): JWT authentication
- ⚠️ Warning: JWT secrets not imported for security
Header Manipulation:
- _parse_proxy_rewrite_plugin(): Request header manipulation
- _parse_response_rewrite_plugin(): Response header manipulation
- _enrich_response_headers(): Merges response headers from multiple plugins
CORS:
- _parse_cors_plugin(): Parses CORS config
- origins, methods, headers, credentials, max_age
- Handles comma-separated strings and wildcards
Utilities:
- get_import_warnings(): Returns list of import warnings for user review
CLI Command: gal-cli.py:225-368 (already implemented)
Tests: tests/test_import_apisix.py - 22 tests, all passing ✅
Test Coverage: - Basic Import (3 tests): Simple service, service+route, JSON format - Upstream (2 tests): Nodes with weights, all LB algorithms (parametrized) - Health Checks (3 tests): Active, passive, combined - Rate Limiting (2 tests): limit-req plugin, limit-count plugin with conversion - Authentication (3 tests): key-auth, basic-auth, JWT (all with warning checks) - Headers (2 tests): proxy-rewrite, response-rewrite plugins - CORS (1 test): Full CORS configuration - Multi-Service (1 test): 3 services with routes - Errors (3 tests): Invalid YAML, empty config, service without name - Combined (1 test): Production config with all features - Circuit Breaker (1 test): api-breaker warning generation
Supported Features:
- ✅ Services & Upstreams (ID-based linking: service.upstream_id → upstream.id)
- ✅ Nodes with weights ({"host:port": weight} dict format with rsplit parsing)
- ✅ Load Balancing (4 algorithms: roundrobin, chash, ewma, least_conn)
- ✅ Active Health Checks (http_path, interval, timeout, healthy/unhealthy successes/failures)
- ✅ Passive Health Checks (outlier detection via checks.passive)
- ✅ Rate Limiting (limit-req leaky bucket, limit-count fixed window with count/time_window → req/s)
- ✅ API Key Authentication (header-based, with security warning)
- ✅ Basic Authentication (with security warning for user credentials)
- ✅ JWT Authentication (with security warning for secrets)
- ✅ Request Header Transformation (proxy-rewrite plugin)
- ✅ Response Header Transformation (response-rewrite plugin)
- ✅ CORS (origins, methods, headers, credentials, max_age with wildcard support)
- ✅ Circuit Breaker warning (api-breaker plugin detection)
- ✅ Multiple Services & Routes
- ✅ YAML & JSON format support
Import Warnings: - ⚠️ API keys not imported (security) - configure in APISIX consumers - ⚠️ Basic auth user credentials not imported (security) - configure in consumers - ⚠️ JWT secrets not imported (security) - configure manually - ⚠️ Circuit breaker plugin requires manual review
Example Input/Output:
# Input: apisix.yaml
services:
- id: api_service
name: api_service
upstream_id: api_upstream
upstreams:
- id: api_upstream
type: roundrobin
nodes:
"api-1:8080": 100
"api-2:8080": 100
checks:
active:
http_path: /health
interval: 10
healthy:
successes: 2
unhealthy:
http_failures: 3
routes:
- id: api_route
uri: /api/v1
methods: [GET, POST]
service_id: api_service
plugins:
limit-req:
rate: 100
burst: 200
key-auth:
header: apikey
# Output: gal-config.yaml
services:
- name: api_service
type: rest
protocol: http
upstream:
targets:
- {host: api-1, port: 8080, weight: 100}
- {host: api-2, port: 8080, weight: 100}
load_balancer: {algorithm: round_robin}
health_check:
active:
enabled: true
http_path: /health
interval: 10s
unhealthy_threshold: 3
healthy_threshold: 2
routes:
- path_prefix: /api/v1
methods: [GET, POST]
rate_limit:
enabled: true
requests_per_second: 100
burst: 200
key_type: ip_address
authentication:
enabled: true
type: api_key
api_key: {keys: [], key_name: apikey, in_location: header}
Coverage: apisix.py: 8% → 33% (improved by 25%)
📖 Detail-Dokumentation: docs/import/apisix.md
📦 Feature 4: Traefik Import (YAML Parser)¶
Status: ✅ IMPLEMENTED | Effort: 1 Woche | Release: v1.3.0-alpha2 | Commit: TBD
✅ Implementation Summary¶
Provider Implementation: gal/providers/traefik.py:662-978 (~312 lines, 10 helper methods)
class TraefikProvider(Provider):
def parse(self, provider_config: str) -> Config:
"""Parse Traefik YAML configuration to GAL format.
Traefik has static config (entrypoints, providers) and
dynamic config (routers, services, middlewares). This parser
handles dynamic config files.
"""
traefik_config = yaml.safe_load(provider_config)
# Traefik structure: http.routers, http.services, http.middlewares
http_config = traefik_config.get("http", {})
# Create default global config
global_config = GlobalConfig(host="0.0.0.0", port=80, timeout="30s")
return Config(
version="1.0",
provider="traefik",
global_config=global_config,
services=self._parse_services(traefik_config)
)
Helper Methods (10 methods):
Service Parsing:
- _parse_services(): Orchestrates service parsing from Traefik config
- _parse_service(): Converts Traefik service → GAL Service (from loadBalancer.servers)
- _parse_health_check(): Extracts passive health checks (Traefik OSS limitation)
- ⚠️ Warning: Traefik OSS only supports passive health checks
Router & Route Parsing:
- _parse_router(): Converts Traefik router to GAL route with middleware parsing
- _extract_path_from_rule(): Extracts path from Traefik rule matchers
- Supports: PathPrefix(\/api`),Path(`/exact`),Host(`...`) && PathPrefix(`...`)`
Middleware Parsing:
- _parse_rate_limit_middleware(): Converts rateLimit middleware
- average (per second) → requests_per_second
- burst → burst
- _parse_basic_auth_middleware(): Basic auth middleware
- ⚠️ Warning: Users are hashed - configure manually in GAL
- _parse_headers_middleware(): Request/response header manipulation
- customRequestHeaders → request_add
- customResponseHeaders → response_add
CORS Extraction:
- _extract_cors_from_headers(): Extracts CORS config from Access-Control-* response headers
- Parses: Allow-Origin, Allow-Methods, Allow-Headers, Allow-Credentials, Max-Age
- Removes CORS headers from response_add after extraction
Utilities:
- get_import_warnings(): Returns list of import warnings for user review
CLI Command: gal-cli.py:225-368 (already implemented)
Tests: tests/test_import_traefik.py - 24 tests, all passing ✅
Test Coverage: - TestTraefikImportBasic (3 tests): Simple service, service+router, multiple servers - TestTraefikImportRouters (3 tests): PathPrefix, exact Path, complex rules with Host - TestTraefikImportHealthChecks (1 test): Health check with OSS limitation warning - TestTraefikImportStickySession (2 tests): Sticky sessions with custom/default cookie name - TestTraefikImportRateLimiting (1 test): rateLimit middleware - TestTraefikImportAuthentication (1 test): basicAuth middleware with warning - TestTraefikImportHeaders (2 tests): Request headers, response headers - TestTraefikImportCORS (2 tests): CORS extraction from headers, wildcard origins - TestTraefikImportMultiService (1 test): 3 services with routers - TestTraefikImportMultipleMiddlewares (1 test): Multiple middlewares on one route - TestTraefikImportErrors (5 tests): Invalid YAML, empty config, no services, incomplete service/router - TestTraefikImportWarnings (1 test): Path manipulation middleware warning - TestTraefikImportCombined (1 test): Production config with all features
Supported Features: - ✅ Services & Routers (http.services.loadBalancer.servers → GAL services) - ✅ Load Balancer (servers with URL parsing: http://host:port) - ✅ Health Checks (passive only - Traefik OSS limitation) - ✅ Sticky Sessions (cookie-based with custom names) - ✅ Load Balancing (round_robin default) - ✅ Rate Limiting (rateLimit middleware: average, burst) - ✅ Basic Authentication (basicAuth middleware with hashed users warning) - ✅ Request Header Manipulation (customRequestHeaders) - ✅ Response Header Manipulation (customResponseHeaders) - ✅ CORS (extracted from Access-Control-* response headers) - ✅ Multiple Services & Routes - ✅ Router Rule Parsing (PathPrefix, Path, Host combinations) - ✅ Multiple Middlewares per Route
Import Warnings: - ⚠️ Traefik OSS only supports passive health checks - config may be simplified - ⚠️ Basic auth users are hashed - configure manually in GAL - ⚠️ Path manipulation middleware not imported (addPrefix, stripPrefix)
Example Input/Output:
# Input: traefik.yaml
http:
routers:
api-router:
rule: PathPrefix(`/api/v1`)
service: api-service
middlewares:
- rate-limit
- cors-headers
services:
api-service:
loadBalancer:
servers:
- url: http://api-1:8080
- url: http://api-2:8080
healthCheck:
path: /health
interval: 10s
timeout: 5s
sticky:
cookie:
name: lb
middlewares:
rate-limit:
rateLimit:
average: 100
burst: 200
cors-headers:
headers:
customResponseHeaders:
Access-Control-Allow-Origin: "https://app.example.com"
Access-Control-Allow-Methods: "GET,POST,PUT,DELETE"
Access-Control-Allow-Credentials: "true"
Access-Control-Max-Age: "86400"
# Output: gal-config.yaml
services:
- name: api-service
type: rest
protocol: http
upstream:
targets:
- {host: api-1, port: 8080}
- {host: api-2, port: 8080}
load_balancer:
algorithm: round_robin
sticky_sessions: true
cookie_name: lb
health_check:
passive:
enabled: true
max_failures: 3
routes:
- path_prefix: /api/v1
rate_limit:
enabled: true
requests_per_second: 100
burst: 200
key_type: ip_address
cors:
enabled: true
allowed_origins: ["https://app.example.com"]
allowed_methods: ["GET", "POST", "PUT", "DELETE"]
allow_credentials: true
max_age: "86400"
Coverage: traefik.py: 6% → 32% (improved by 26%)
📖 Detail-Dokumentation: docs/import/traefik.md
📦 Feature 5: Nginx Import (Custom Parser)¶
Status: ✅ IMPLEMENTED | Effort: 2 Wochen | Release: v1.3.0-beta1 | Commit: TBD
✅ Implementation Summary¶
Provider Implementation: gal/providers/nginx.py:829-1280 (~450 lines, 11 helper methods)
class NginxProvider(Provider):
def parse(self, provider_config: str) -> Config:
"""Parse Nginx configuration to GAL format.
Parses nginx.conf format with custom regex-based parser.
Extracts upstreams, servers, locations, and directives.
"""
# Remove comments
config_text = self._remove_comments(provider_config)
# Extract http block
http_block = self._extract_http_block(config_text)
# Parse upstreams
upstreams = self._parse_upstreams(http_block)
# Parse rate limiting zones
rate_limit_zones = self._parse_rate_limit_zones(http_block)
# Parse servers with locations
services = self._parse_servers(http_block, upstreams, rate_limit_zones)
return Config(
version="1.0",
provider="nginx",
global_config=GlobalConfig(host="0.0.0.0", port=80, timeout="60s"),
services=services,
)
Helper Methods (11 methods):
Parsing Infrastructure:
- _remove_comments(): Removes # comments from nginx.conf
- _extract_http_block(): Extracts http {} block using brace counting
- _extract_blocks(): Generic block extraction with brace counting
- _extract_location_blocks(): Extracts location blocks with paths
Upstream & Server Parsing:
- _parse_upstreams(): Parses upstream blocks → targets, algorithms
- Algorithms: round_robin (default), least_conn, ip_hash
- Server weights and passive health check parameters (max_fails, fail_timeout)
- _parse_rate_limit_zones(): Parses limit_req_zone directives
- Converts r/s, r/m, r/h, r/d to requests_per_second
- _parse_servers(): Orchestrates server block parsing
- _parse_server_block(): Parses single server with locations
Route & Feature Parsing:
- _parse_location_block(): Parses location → Route with features
- Rate limiting: limit_req zone + burst
- Basic auth: auth_basic (htpasswd warning)
- Headers: proxy_set_header, add_header
- CORS: Extracted from Access-Control-* headers
- _parse_headers(): Parses proxy_set_header and add_header directives
- _extract_cors_from_headers(): Extracts CORS config from response headers
CLI Command: gal-cli.py:225-368 (already implemented)
Tests: tests/test_import_nginx.py - 18 tests, all passing ✅
Test Coverage: - TestNginxImportBasic (3 tests): Simple upstream, multiple servers, comments - TestNginxImportLoadBalancing (3 tests): round_robin, least_conn, ip_hash - TestNginxImportHealthChecks (1 test): Passive health check parameters - TestNginxImportRateLimiting (2 tests): Per second, per minute conversion - TestNginxImportAuthentication (1 test): Basic auth with htpasswd warning - TestNginxImportHeaders (2 tests): Request headers (proxy_set_header), response headers (add_header) - TestNginxImportCORS (2 tests): CORS extraction from headers, wildcard origins - TestNginxImportMultipleLocations (1 test): Multiple location blocks in server - TestNginxImportErrors (2 tests): Empty config, no http block - TestNginxImportCombined (1 test): Production config with all features
Supported Features: - ✅ Upstream Blocks (servers with host:port) - ✅ Load Balancing (round_robin, least_conn, ip_hash, weighted) - ✅ Passive Health Checks (max_fails, fail_timeout) - ✅ Rate Limiting (limit_req_zone with r/s, r/m, r/h, r/d conversion) - ✅ Basic Authentication (auth_basic with htpasswd warning) - ✅ Request Header Manipulation (proxy_set_header) - ✅ Response Header Manipulation (add_header) - ✅ CORS (extracted from Access-Control-* response headers) - ✅ Multiple Location Blocks per Server - ✅ Comment Removal - ✅ Nested Block Parsing (brace counting)
Import Warnings: - ⚠️ Basic auth detected - htpasswd file not imported (configure manually)
Example Input/Output:
# Input: nginx.conf
events {}
http {
limit_req_zone $binary_remote_addr zone=api_rate:10m rate=100r/s;
upstream upstream_api {
least_conn;
server api-1:8080 weight=2 max_fails=3 fail_timeout=30s;
server api-2:8080;
}
server {
listen 80;
location /api/v1 {
limit_req zone=api_rate burst=200;
proxy_set_header X-Real-IP $remote_addr;
add_header Access-Control-Allow-Origin "https://app.example.com";
add_header Access-Control-Allow-Credentials "true";
proxy_pass http://upstream_api;
}
}
}
# Output: gal-config.yaml
services:
- name: api
type: rest
protocol: http
upstream:
targets:
- {host: api-1, port: 8080, weight: 2}
- {host: api-2, port: 8080}
load_balancer:
algorithm: least_conn
health_check:
passive:
enabled: true
max_failures: 3
routes:
- path_prefix: /api/v1
rate_limit:
enabled: true
requests_per_second: 100
burst: 200
key_type: ip_address
headers:
request_add:
X-Real-IP: $remote_addr
cors:
enabled: true
allowed_origins: ["https://app.example.com"]
allow_credentials: true
Coverage: nginx.py: 6% → 38% (improved by 32%)
📖 Detail-Dokumentation: docs/import/nginx.md
📦 Feature 6: HAProxy Import (Custom Parser)¶
Status: ✅ Completed | Effort: 2 Wochen | Release: v1.3.0-beta2
Scope¶
Parse HAProxy haproxy.cfg (non-YAML!) → GAL Config
Challenge: HAProxy config ist section-based format!
Lösung: Custom Parser (simpler als Nginx - section-basiert)
Mapping:
- frontend → Routing ACLs → GAL routes[]
- backend → Servers → GAL services[], upstream.targets[]
- balance → GAL load_balancer.algorithm (roundrobin, leastconn, source, uri, hdr)
- option httpchk → GAL health_check.active
- cookie → GAL load_balancer.sticky_sessions
- http-request set-header → GAL transformation.headers
Implementation:
from gal.parsers.haproxy_parser import HAProxyConfigParser, SectionType
class HAProxyProvider(Provider):
def parse(self, provider_config: str) -> Config:
parser = HAProxyConfigParser()
sections = parser.parse(provider_config)
global_config = self._parse_global(sections)
services = self._parse_services(sections)
return Config(
version="1.0",
provider="haproxy",
global_config=global_config,
services=services
)
Custom Parser: gal/parsers/haproxy_parser.py (235 lines)
class HAProxyConfigParser:
"""Parse haproxy.cfg section-based format."""
def parse(self, config_text: str) -> List[HAProxySection]:
sections = []
current_section = None
for line in self._preprocess(config_text):
if line.startswith("frontend"):
current_section = HAProxySection(type=SectionType.FRONTEND, ...)
elif line.startswith("backend"):
current_section = HAProxySection(type=SectionType.BACKEND, ...)
else:
current_section.directives.append(self._parse_directive(line))
return sections
CLI Command: gal-cli.py:225-368 (already implemented)
Tests: tests/test_import_haproxy.py - 28 tests, all passing ✅
Test Coverage: - TestHAProxyParserBasic (9 tests): Empty config, global, defaults, frontend, backend, listen, multiple sections, comments - TestHAProxyImportBasic (5 tests): Simple backend, multiple servers, multiple backends, listen section, global config - TestHAProxyImportLoadBalancing (4 tests): roundrobin, leastconn, source, uri algorithms - TestHAProxyImportHealthChecks (3 tests): Simple httpchk, httpchk with path, http-check v2.0+ - TestHAProxyImportStickySessions (1 test): Cookie-based sticky sessions - TestHAProxyImportHeaders (1 test): http-request set-header - TestHAProxyImportRouting (2 tests): Path-based routing with ACLs, default_backend - TestHAProxyImportEdgeCases (3 tests): Backend without servers, unnamed sections, invalid servers - TestHAProxyImportComplex (1 test): Production-like multi-backend config
Supported Features: - ✅ Frontends & Backends (section-based parsing) - ✅ Listen Sections (combined frontend+backend) - ✅ Load Balancing (roundrobin → round_robin, leastconn → least_connections, source → ip_hash, uri → uri_hash) - ✅ Health Checks (option httpchk, http-check v2.0+) - ✅ Sticky Sessions (cookie-based with custom names) - ✅ Server Weights (weight parameter) - ✅ Header Manipulation (http-request set-header → transformation.headers) - ✅ Routing ACLs (path_beg → routes with path_prefix) - ✅ Global Config (defaults, bind addresses) - ✅ Multiple Services & Routes
Parser Coverage: 88% (97 statements, 12 missed)
Example Input/Output:
# Input: haproxy.cfg
frontend http_front
bind *:80
use_backend api_backend if { path_beg /api }
default_backend app_backend
backend api_backend
balance roundrobin
option httpchk GET /health
http-request set-header X-Backend api
server api1 api1.internal:8080 check weight 2
server api2 api2.internal:8080 check weight 1
backend app_backend
balance source
cookie APPID insert indirect
server app1 app1.internal:8080 check cookie app1
server app2 app2.internal:8080 check cookie app2
# Output: gal-config.yaml
services:
- name: api_backend
type: rest
protocol: http
upstream:
targets:
- {host: api1.internal, port: 8080, weight: 2}
- {host: api2.internal, port: 8080, weight: 1}
health_check:
active:
enabled: true
http_path: /health
interval: 10s
timeout: 5s
load_balancer:
algorithm: round_robin
routes:
- path_prefix: /api
- name: app_backend
type: rest
protocol: http
upstream:
targets:
- {host: app1.internal, port: 8080}
- {host: app2.internal, port: 8080}
load_balancer:
algorithm: ip_hash
sticky_sessions: true
cookie_name: APPID
routes:
- path_prefix: /
Files Created:
- gal/parsers/__init__.py (9 lines)
- gal/parsers/haproxy_parser.py (235 lines) - Custom section-based parser
- gal/providers/haproxy.py (+407 lines) - parse() implementation
- tests/test_import_haproxy.py (560+ lines) - Comprehensive test suite
- examples/haproxy/haproxy.cfg (197 lines) - Production-like example
- examples/haproxy/simple-haproxy.cfg (35 lines) - Simple example
📖 Detail-Dokumentation: docs/import/haproxy.md
✅ Feature 7: Compatibility Checker & Comparison¶
Status: 🔄 Pending | Effort: 2 Wochen | Release: v1.3.0-rc1 | Dependencies: Features 1-6
Motivation¶
Nach Import muss der Nutzer wissen: - Funktioniert die GAL-Config auf dem Ziel-Provider? - Welche Features werden unterstützt? - Welcher Provider ist am besten geeignet?
CLI Commands¶
Check Compatibility:
gal validate --config gal-config.yaml --target-provider haproxy
# Output:
# ✓ Config is compatible with HAProxy
# ⚠ Warnings:
# - JWT authentication requires Lua scripting
# - Active health checks fully supported
#
# Compatibility: 95% (19/20 features supported)
Compare Providers:
gal compare --config gal-config.yaml --providers envoy,kong,nginx,haproxy
# Output (table):
# Feature | Envoy | Kong | Nginx | HAProxy
# ------------------|-------|------|-------|--------
# Rate Limiting | ✅ | ✅ | ✅ | ✅
# JWT Auth | ✅ | ✅ | ⚠️ | ⚠️
# Active HC | ✅ | ✅ | ❌ | ✅
# Load Balancing | ✅ | ✅ | ✅ | ✅
#
# Recommendation: Use Envoy or Kong for full compatibility
Implementation¶
File: gal/compatibility.py
class CompatibilityChecker:
"""Check config compatibility with providers."""
def check_provider(self, config: Config, target_provider: str) -> CompatibilityReport:
"""Check if config works on target provider."""
provider = get_provider(target_provider)
report = CompatibilityReport(
provider=target_provider,
compatible=True,
features_supported=[],
features_unsupported=[],
warnings=[]
)
# Check each feature
for service in config.services:
self._check_service_features(service, provider, report)
return report
def compare_providers(self, config: Config, providers: List[str]) -> Dict[str, CompatibilityReport]:
"""Compare config compatibility across providers."""
results = {}
for provider_name in providers:
results[provider_name] = self.check_provider(config, provider_name)
return results
Tests: 40+ tests für Compatibility Checking, Provider Comparison
📖 Detail-Dokumentation: docs/import/compatibility.md
🔀 Feature 8: Migration Assistant (Interactive CLI)¶
Status: ✅ Done | Effort: 2 Wochen | Release: v1.3.0 Final | Dependencies: Features 1-7 | Tests: 31/31 (100%)
Motivation¶
Migration sollte geführt, einfach und sicher sein: - Interaktive Prompts - Automatische Validierung - Migration Report (Markdown) - Recommendations & Next Steps
Interactive Workflow¶
gal migrate
# Interactive prompts:
? Source Provider: nginx
? Source Config: /etc/nginx/nginx.conf
? Target Provider: haproxy
? Output Directory: ./migration/
[1/5] Reading Nginx config...
[2/5] Parsing and analyzing...
[3/5] Converting to GAL format...
[4/5] Validating compatibility with HAProxy...
[5/5] Generating HAProxy config...
✓ Migration complete!
Files created:
- ./migration/gal-config.yaml (GAL format)
- ./migration/haproxy.cfg (HAProxy config)
- ./migration/migration-report.md (Migration report)
Compatibility: 95% (19/20 features)
Warnings: 2
- JWT auth requires Lua (see docs)
- Passive health checks use fall/rise thresholds
Next steps:
1. Review migration-report.md
2. Test haproxy.cfg in staging
3. Deploy to production
Migration Report Format¶
File: migration/migration-report.md
# Migration Report: Nginx → HAProxy
**Date:** 2026-04-15
**Source:** /etc/nginx/nginx.conf
**Target:** HAProxy 2.8
## Summary
- **Compatibility:** 95% (19/20 features)
- **Services Migrated:** 3
- **Routes Migrated:** 12
- **Warnings:** 2
## Features Migrated
✅ **Load Balancing**
- Algorithm: Round Robin → roundrobin
- Targets: 6 backends
✅ **Rate Limiting**
- IP-based: 100 req/s
- Converted to stick-table
⚠️ **Authentication**
- Basic Auth: ✅ Supported
- JWT Auth: ⚠️ Requires Lua scripting
## Warnings & Recommendations
1. **JWT Authentication**
- Nginx uses OpenResty/Lua
- HAProxy requires Lua scripting or external auth
- **Recommendation:** Use Kong or Envoy for native JWT
2. **Passive Health Checks**
- Nginx: max_fails, fail_timeout
- HAProxy: fall, rise thresholds
- **Action:** Review and adjust thresholds
## Testing Checklist
- [ ] Test in staging environment
- [ ] Verify all 12 routes
- [ ] Check load balancing distribution
- [ ] Validate rate limiting behavior
- [ ] Monitor backend health
- [ ] Performance comparison
## Next Steps
1. ✅ Review this report
2. ⏳ Test in staging
3. ⏳ Adjust JWT authentication
4. ⏳ Deploy to production
5. ⏳ Monitor and validate
Tests: 30+ tests für Interactive Workflow, Report Generation
📖 Detail-Dokumentation: docs/import/migration.md
🗓️ Timeline (12 Wochen)¶
Phase 1: YAML Parsers (Weeks 1-4) → v1.3.0-alpha1, alpha2¶
- Week 1: Feature 1 - Envoy Import + Shared Infrastructure
- Week 2: Feature 2 - Kong Import → Release v1.3.0-alpha1
- Week 3: Feature 3 - APISIX Import
- Week 4: Feature 4 - Traefik Import → Release v1.3.0-alpha2
Phase 2: Custom Parsers (Weeks 5-8) → v1.3.0-beta1, beta2¶
- Weeks 5-6: Feature 5 - Nginx Import (Custom Parser) → Release v1.3.0-beta1
- Weeks 7-8: Feature 6 - HAProxy Import (Custom Parser) → Release v1.3.0-beta2
Phase 3: Compatibility & Migration (Weeks 9-12) → v1.3.0-rc1, Final¶
- Weeks 9-10: Feature 7 - Compatibility Checker → Release v1.3.0-rc1
- Weeks 11-12: Feature 8 - Migration Assistant → Release v1.3.0 Final
🎯 Use Cases¶
Use Case 1: Nginx → HAProxy Migration¶
Scenario: E-Commerce mit Nginx möchte zu HAProxy wechseln.
# 1. Import Nginx config
gal import --provider nginx --input /etc/nginx/nginx.conf --output gal-config.yaml
# 2. Check compatibility
gal validate --config gal-config.yaml --target-provider haproxy
# 3. Generate HAProxy config
gal generate --config gal-config.yaml --provider haproxy --output haproxy.cfg
Use Case 2: Kong → Envoy Migration¶
Scenario: Startup mit Kong möchte zu Envoy für Service Mesh.
Use Case 3: Multi-Provider Deployment¶
Scenario: Großunternehmen will gleiche Config auf verschiedenen Providern.
# 1. Import production HAProxy config
gal import --provider haproxy --input haproxy-prod.cfg --output gal-config.yaml
# 2. Generate for all providers
gal generate-all --config gal-config.yaml
# Result: envoy.yaml, kong.yaml, apisix.json, traefik.yaml, nginx.conf, haproxy.cfg
📊 Success Metrics - ✅ ACHIEVED¶
Deliverables (100% Complete)¶
Code:
- ✅ Provider Interface Extension (parse method)
- ✅ 6 Provider Parser (envoy, kong, apisix, traefik, nginx, haproxy)
- ✅ 2 Custom Parsers (nginx_parser.py 237 lines, haproxy_parser.py 235 lines)
- ✅ CLI Commands: import-config, check-compatibility, compare-providers, migrate
- ✅ Compatibility Checker (compatibility.py 601 lines, 86% coverage)
- ✅ Tests: 185 tests (15+21+22+24+18+28+26+31) - All Passing ✅
Documentation: - ✅ docs/import/compatibility.md (550+ lines, German) - ✅ docs/import/migration.md (325 lines, German) - ✅ Import Guides pro Provider (6 × 800+ lines = 4800+ lines total) - ✅ Feature Coverage Tables (3540+ lines in provider guides) - ✅ Migration Examples & Use Cases
Examples: - ✅ examples/haproxy/ (2 configs: haproxy.cfg, simple-haproxy.cfg) - ✅ Migration Workflows (all 36 provider combinations supported)
Coverage Achieved¶
- Parser Coverage: 88% für Custom Parsers (nginx, haproxy)
- Feature Mapping: 90%+ der Core Features
- Test Coverage: 549 Total Tests (v1.2.0: 364 → +185 new tests)
- Code Coverage: 89% overall (maintained from v1.2.0)
Statistics¶
- 6 Import Guides: 4800+ lines documentation
- 2 Feature Docs: 875+ lines (compatibility.md, migration.md)
- Provider Feature Coverage: 3540+ lines in 6 provider guides
- Total Documentation: 9200+ lines new documentation
✅ Release Complete¶
Released: 2025-10-19 Final Status: All 8 Features Implemented & Tested Mission: Provider Lock-in brechen - ✅ ACCOMPLISHED
Release Milestones (All Complete)¶
- ✅ v1.3.0-alpha1 (Envoy + Kong Import)
- ✅ v1.3.0-alpha2 (+ APISIX + Traefik Import)
- ✅ v1.3.0-beta1 (+ Nginx Import)
- ✅ v1.3.0-beta2 (+ HAProxy Import)
- ✅ v1.3.0-rc1 (+ Compatibility Checker)
- ✅ v1.3.0 Final (+ Migration Assistant)
Links¶
- GitHub Release: https://github.com/pt9912/x-gal/releases/tag/v1.3.0
- PyPI: https://pypi.org/project/gal-gateway/1.3.0/
- Docker: ghcr.io/pt9912/x-gal:v1.3.0
Next Milestone: v1.4.0 (Q3 2026) - Advanced Traffic & Multi-Cloud + gRPC Transformations