From 1fbd9ab65d0d028a77aa634fa4563b6baa4db5fd Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Thu, 23 Jul 2026 17:34:48 +0200 Subject: [PATCH] refactor(core): default gateway config Signed-off-by: Evan Lezar --- crates/openshell-core/src/config.rs | 30 ++++++++++++-------- crates/openshell-server/src/grpc/auth_rpc.rs | 4 +-- crates/openshell-server/src/grpc/mod.rs | 2 +- crates/openshell-server/src/lib.rs | 22 +++++++------- crates/openshell-server/src/multiplex.rs | 14 ++++----- 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/crates/openshell-core/src/config.rs b/crates/openshell-core/src/config.rs index b200eded64..b94072b586 100644 --- a/crates/openshell-core/src/config.rs +++ b/crates/openshell-core/src/config.rs @@ -897,6 +897,12 @@ impl Config { } } +impl Default for Config { + fn default() -> Self { + Self::new(None) + } +} + impl Default for ServiceRoutingConfig { fn default() -> Self { Self { @@ -1035,24 +1041,24 @@ mod tests { #[test] fn config_defaults_to_loopback_bind_address() { let expected: SocketAddr = "127.0.0.1:17670".parse().expect("valid address"); - assert_eq!(Config::new(None).bind_address, expected); + assert_eq!(Config::default().bind_address, expected); } #[test] fn config_new_disables_health_bind_by_default() { - let cfg = Config::new(None); + let cfg = Config::default(); assert!(cfg.health_bind_address.is_none()); } #[test] fn config_disables_unauthenticated_users_by_default() { - let cfg = Config::new(None); + let cfg = Config::default(); assert!(!cfg.auth.allow_unauthenticated_users); } #[test] fn config_defaults_to_builtin_and_user_provider_profile_sources() { - let cfg = Config::new(None); + let cfg = Config::default(); assert_eq!( cfg.provider_profile_sources, vec![ @@ -1105,21 +1111,21 @@ mod tests { #[test] fn grpc_rate_limit_requires_positive_pair() { - assert!(Config::new(None).grpc_rate_limit().is_none()); + assert!(Config::default().grpc_rate_limit().is_none()); assert!( - Config::new(None) + Config::default() .with_grpc_rate_limit(Some(10), None) .grpc_rate_limit() .is_none() ); assert!( - Config::new(None) + Config::default() .with_grpc_rate_limit(Some(0), Some(60)) .grpc_rate_limit() .is_none() ); assert_eq!( - Config::new(None) + Config::default() .with_grpc_rate_limit(Some(10), Some(60)) .grpc_rate_limit(), Some((10, Duration::from_secs(60))) @@ -1128,7 +1134,7 @@ mod tests { #[test] fn service_routing_allows_loopback_plaintext_http_by_default() { - let cfg = Config::new(None); + let cfg = Config::default(); assert_eq!( cfg.service_routing.base_domains, vec![DEFAULT_SERVICE_ROUTING_DOMAIN.to_string()] @@ -1138,7 +1144,7 @@ mod tests { #[test] fn server_sans_update_preserves_loopback_plaintext_http_flag() { - let cfg = Config::new(None) + let cfg = Config::default() .with_loopback_service_http(false) .with_server_sans(["*.dev.openshell.localhost"]); @@ -1154,7 +1160,7 @@ mod tests { #[test] fn service_routing_domains_are_derived_from_wildcard_server_sans() { - let cfg = Config::new(None).with_server_sans([ + let cfg = Config::default().with_server_sans([ "gateway.example.com", "*.apps.example.com", "127.0.0.1", @@ -1175,7 +1181,7 @@ mod tests { #[test] fn config_with_health_bind_address_sets_address() { let addr: SocketAddr = "0.0.0.0:9090".parse().expect("valid address"); - let cfg = Config::new(None).with_health_bind_address(addr); + let cfg = Config::default().with_health_bind_address(addr); assert_eq!(cfg.health_bind_address, Some(addr)); } diff --git a/crates/openshell-server/src/grpc/auth_rpc.rs b/crates/openshell-server/src/grpc/auth_rpc.rs index f4cb6a872a..b7263ab988 100644 --- a/crates/openshell-server/src/grpc/auth_rpc.rs +++ b/crates/openshell-server/src/grpc/auth_rpc.rs @@ -169,7 +169,7 @@ mod tests { ); let compute = new_test_runtime(store.clone()).await; let mut state = ServerState::new( - Config::new(None).with_database_url("sqlite::memory:?cache=shared"), + Config::default().with_database_url("sqlite::memory:?cache=shared"), store, compute, SandboxIndex::new(), @@ -348,7 +348,7 @@ mod tests { ); let compute = new_test_runtime(store.clone()).await; let state = Arc::new(ServerState::new( - Config::new(None).with_database_url("sqlite::memory:?cache=shared"), + Config::default().with_database_url("sqlite::memory:?cache=shared"), store, compute, SandboxIndex::new(), diff --git a/crates/openshell-server/src/grpc/mod.rs b/crates/openshell-server/src/grpc/mod.rs index ecd96ea90d..544c55b934 100644 --- a/crates/openshell-server/src/grpc/mod.rs +++ b/crates/openshell-server/src/grpc/mod.rs @@ -807,7 +807,7 @@ pub mod test_support { crate::ensure_default_workspace(&store).await.unwrap(); let compute = new_test_runtime(store.clone()).await; Arc::new(ServerState::new( - Config::new(None).with_database_url("sqlite::memory:?cache=shared"), + Config::default().with_database_url("sqlite::memory:?cache=shared"), store, compute, SandboxIndex::new(), diff --git a/crates/openshell-server/src/lib.rs b/crates/openshell-server/src/lib.rs index a75534d397..6cef9b706d 100644 --- a/crates/openshell-server/src/lib.rs +++ b/crates/openshell-server/src/lib.rs @@ -1080,7 +1080,7 @@ mod tests { ); let compute = crate::compute::new_test_runtime(store.clone()).await; Arc::new(ServerState::new( - Config::new(None) + Config::default() .with_database_url("sqlite::memory:?cache=shared") .with_bind_address(bind_addr) .with_server_sans(["*.dev.openshell.localhost"]) @@ -1343,7 +1343,7 @@ mod tests { #[test] fn configured_compute_driver_triggers_auto_detection_when_empty() { - let config = Config::new(None).with_compute_drivers(std::iter::empty::()); + let config = Config::default().with_compute_drivers(std::iter::empty::()); // Empty drivers triggers auto-detection, which may return Some or None // depending on the environment. This test verifies the auto-detection path // is taken rather than immediately returning an error. @@ -1376,7 +1376,7 @@ mod tests { #[test] fn configured_compute_driver_rejects_multiple_entries() { - let config = Config::new(None) + let config = Config::default() .with_compute_drivers([ComputeDriverKind::Kubernetes, ComputeDriverKind::Podman]); let err = configured_compute_driver(&config, test_driver_startup(&config, None)).unwrap_err(); @@ -1389,7 +1389,7 @@ mod tests { #[test] fn configured_compute_driver_accepts_podman() { - let config = Config::new(None).with_compute_drivers([ComputeDriverKind::Podman]); + let config = Config::default().with_compute_drivers([ComputeDriverKind::Podman]); let driver = configured_compute_driver(&config, test_driver_startup(&config, None)).unwrap(); assert!(matches!( @@ -1400,7 +1400,7 @@ mod tests { #[test] fn configured_compute_driver_accepts_vm() { - let config = Config::new(None).with_compute_drivers([ComputeDriverKind::Vm]); + let config = Config::default().with_compute_drivers([ComputeDriverKind::Vm]); let driver = configured_compute_driver(&config, test_driver_startup(&config, None)).unwrap(); assert!(matches!( @@ -1411,7 +1411,7 @@ mod tests { #[test] fn configured_compute_driver_accepts_docker() { - let config = Config::new(None).with_compute_drivers([ComputeDriverKind::Docker]); + let config = Config::default().with_compute_drivers([ComputeDriverKind::Docker]); let driver = configured_compute_driver(&config, test_driver_startup(&config, None)).unwrap(); assert!(matches!( @@ -1422,7 +1422,7 @@ mod tests { #[test] fn configured_compute_driver_resolves_named_remote() { - let config = Config::new(None).with_compute_drivers(["kyma"]); + let config = Config::default().with_compute_drivers(["kyma"]); let driver = configured_compute_driver(&config, test_driver_startup(&config, None)).unwrap(); @@ -1439,7 +1439,7 @@ mod tests { #[test] fn configured_compute_driver_rejects_vm_endpoint_from_config() { - let config = Config::new(None) + let config = Config::default() .with_compute_drivers([ComputeDriverKind::Vm]) .with_compute_driver_endpoint("vm", "/run/openshell/vm.sock"); @@ -1455,7 +1455,7 @@ mod tests { #[test] fn configured_compute_driver_rejects_builtin_endpoint() { - let config = Config::new(None) + let config = Config::default() .with_compute_drivers([ComputeDriverKind::Docker]) .with_compute_driver_endpoint("docker", "/run/openshell/docker.sock"); @@ -1472,7 +1472,7 @@ mod tests { #[test] fn kubernetes_sandbox_jwt_expiry_disabled_warns_for_zero_ttl() { fn config_with_jwt_ttl(ttl_secs: u64) -> Config { - let mut config = Config::new(None); + let mut config = Config::default(); config.gateway_jwt = Some(openshell_core::GatewayJwtConfig { signing_key_path: "/tmp/signing.pem".into(), public_key_path: "/tmp/public.pem".into(), @@ -1489,7 +1489,7 @@ mod tests { assert!(!kubernetes_sandbox_jwt_expiry_disabled( &config_with_jwt_ttl(3600) )); - assert!(!kubernetes_sandbox_jwt_expiry_disabled(&Config::new(None))); + assert!(!kubernetes_sandbox_jwt_expiry_disabled(&Config::default())); } #[test] diff --git a/crates/openshell-server/src/multiplex.rs b/crates/openshell-server/src/multiplex.rs index 83e27d27cb..4bbded11f6 100644 --- a/crates/openshell-server/src/multiplex.rs +++ b/crates/openshell-server/src/multiplex.rs @@ -1484,7 +1484,7 @@ mod tests { // An exhausted limiter must report ready even when the inner service is // pending, so `call` returns RESOURCE_EXHAUSTED instead of waiting on // inner backpressure. - let config = Config::new(None).with_grpc_rate_limit(Some(1), Some(60)); + let config = Config::default().with_grpc_rate_limit(Some(1), Some(60)); let limiter = GrpcRateLimiter::from_config(&config).expect("limiter should be enabled"); // Consume the single token so the limiter is exhausted. assert!(limiter.allow()); @@ -1499,7 +1499,7 @@ mod tests { assert_eq!(grpc_status_from_response(&response), "8"); // A limiter with capacity must still respect inner backpressure. - let config = Config::new(None).with_grpc_rate_limit(Some(1), Some(60)); + let config = Config::default().with_grpc_rate_limit(Some(1), Some(60)); let limiter = GrpcRateLimiter::from_config(&config); let mut with_capacity = GrpcRateLimitService::new(PendingInnerService::new(), limiter); assert!( @@ -1515,7 +1515,7 @@ mod tests { // rate-limit window then rolls over before `call`, the request must // still be rejected rather than forwarded to an inner service that // never reported readiness (a Tower contract violation). - let config = Config::new(None).with_grpc_rate_limit(Some(1), Some(60)); + let config = Config::default().with_grpc_rate_limit(Some(1), Some(60)); let limiter = GrpcRateLimiter::from_config(&config).expect("limiter should be enabled"); // Exhaust the single token. assert!(limiter.allow()); @@ -1560,7 +1560,7 @@ mod tests { #[tokio::test] async fn grpc_rate_limit_returns_resource_exhausted_after_limit() { - let config = Config::new(None).with_grpc_rate_limit(Some(1), Some(60)); + let config = Config::default().with_grpc_rate_limit(Some(1), Some(60)); let limiter = GrpcRateLimiter::from_config(&config); let calls = Arc::new(AtomicUsize::new(0)); let mut service = GrpcRateLimitService::new( @@ -1592,7 +1592,7 @@ mod tests { #[tokio::test] async fn grpc_rate_limit_disabled_passes_requests_through() { - let config = Config::new(None).with_grpc_rate_limit(Some(0), Some(60)); + let config = Config::default().with_grpc_rate_limit(Some(0), Some(60)); let limiter = GrpcRateLimiter::from_config(&config); let calls = Arc::new(AtomicUsize::new(0)); let mut service = GrpcRateLimitService::new( @@ -1617,7 +1617,7 @@ mod tests { #[tokio::test] async fn grpc_rate_limit_resets_after_window() { - let config = Config::new(None).with_grpc_rate_limit(Some(1), Some(60)); + let config = Config::default().with_grpc_rate_limit(Some(1), Some(60)); let limiter = GrpcRateLimiter::from_config(&config).expect("limiter should be enabled"); let calls = Arc::new(AtomicUsize::new(0)); let mut service = GrpcRateLimitService::new( @@ -1660,7 +1660,7 @@ mod tests { #[tokio::test] async fn grpc_rate_limit_state_is_shared_across_service_clones() { - let config = Config::new(None).with_grpc_rate_limit(Some(1), Some(60)); + let config = Config::default().with_grpc_rate_limit(Some(1), Some(60)); let limiter = GrpcRateLimiter::from_config(&config); let calls = Arc::new(AtomicUsize::new(0)); let mut first_service = GrpcRateLimitService::new(