@@ -163,16 +163,32 @@ impl PodmanComputeDriver {
163163 const MAX_PING_RETRIES : u32 = 5 ;
164164 const PING_RETRY_DELAY : Duration = Duration :: from_secs ( 2 ) ;
165165
166- if !config. socket_path . exists ( ) {
166+ // Explicit configuration wins; otherwise probe for a responsive socket.
167+ // Unlike Docker, Podman has no single well-known default path, so
168+ // there is no further fallback if neither resolves.
169+ let socket_path = config
170+ . socket_path
171+ . clone ( )
172+ . or_else ( openshell_core:: config:: detect_podman_socket)
173+ . ok_or_else ( || {
174+ PodmanApiError :: InvalidInput (
175+ "no responsive Podman API socket found; set OPENSHELL_PODMAN_SOCKET \
176+ or configure socket_path"
177+ . to_string ( ) ,
178+ )
179+ } ) ?;
180+ config. socket_path = Some ( socket_path. clone ( ) ) ;
181+
182+ if !socket_path. exists ( ) {
167183 if cfg ! ( target_os = "macos" ) {
168184 warn ! (
169- path = %config . socket_path. display( ) ,
185+ path = %socket_path. display( ) ,
170186 "Podman socket not found; is podman machine running? \
171187 Try `podman machine start` or set OPENSHELL_PODMAN_SOCKET to override."
172188 ) ;
173189 } else {
174190 warn ! (
175- path = %config . socket_path. display( ) ,
191+ path = %socket_path. display( ) ,
176192 "Podman socket not found; is the Podman service running? \
177193 Set OPENSHELL_PODMAN_SOCKET or XDG_RUNTIME_DIR to override."
178194 ) ;
@@ -186,7 +202,7 @@ impl PodmanComputeDriver {
186202 config. validate_runtime_limits ( ) ?;
187203 config. validate_host_gateway_ip ( ) ?;
188204
189- let client = PodmanClient :: new ( config . socket_path . clone ( ) ) ;
205+ let client = PodmanClient :: new ( socket_path) ;
190206
191207 // Verify connectivity, retrying briefly to tolerate transient socket
192208 // unavailability (e.g. podman.socket restarting after a package
@@ -774,7 +790,7 @@ impl PodmanComputeDriver {
774790 gpu_inventory : CdiGpuInventory ,
775791 allow_all_default_gpu : bool ,
776792 ) -> Self {
777- let client = PodmanClient :: new ( config. socket_path . clone ( ) ) ;
793+ let client = PodmanClient :: new ( config. socket_path . clone ( ) . unwrap_or_default ( ) ) ;
778794 let refresh_inventory = gpu_inventory. clone ( ) ;
779795 Self {
780796 client,
@@ -850,6 +866,59 @@ mod tests {
850866 use std:: fs;
851867 use std:: path:: PathBuf ;
852868
869+ // ── socket resolution ───────────────────────────────────────────────
870+
871+ /// Restores env vars on drop, even if the test body panics.
872+ struct EnvVarGuard ( Vec < ( & ' static str , Option < String > ) > ) ;
873+
874+ impl EnvVarGuard {
875+ #[ allow( unsafe_code) ] // std::env::set_var requires unsafe in Rust 2024
876+ fn set ( vars : & [ ( & ' static str , & str ) ] ) -> Self {
877+ let saved = vars
878+ . iter ( )
879+ . map ( |( name, value) | {
880+ let previous = std:: env:: var ( name) . ok ( ) ;
881+ unsafe { std:: env:: set_var ( name, value) } ;
882+ ( * name, previous)
883+ } )
884+ . collect ( ) ;
885+ Self ( saved)
886+ }
887+ }
888+
889+ impl Drop for EnvVarGuard {
890+ #[ allow( unsafe_code) ] // std::env::set_var/remove_var require unsafe in Rust 2024
891+ fn drop ( & mut self ) {
892+ for ( name, previous) in & self . 0 {
893+ unsafe {
894+ match previous {
895+ Some ( value) => std:: env:: set_var ( name, value) ,
896+ None => std:: env:: remove_var ( name) ,
897+ }
898+ }
899+ }
900+ }
901+ }
902+
903+ #[ tokio:: test]
904+ async fn new_returns_config_error_when_no_socket_is_configured_or_detected ( ) {
905+ let _guard = EnvVarGuard :: set ( & [
906+ ( "OPENSHELL_PODMAN_SOCKET" , "/nonexistent/podman.sock" ) ,
907+ ( "XDG_RUNTIME_DIR" , "/nonexistent/xdg" ) ,
908+ ( "HOME" , "/nonexistent/home" ) ,
909+ ] ) ;
910+
911+ let config = PodmanComputeConfig {
912+ socket_path : None ,
913+ ..PodmanComputeConfig :: default ( )
914+ } ;
915+ let err = PodmanComputeDriver :: new ( config)
916+ . await
917+ . expect_err ( "no socket is configured or reachable" ) ;
918+
919+ assert ! ( err. to_string( ) . contains( "no responsive Podman API socket" ) ) ;
920+ }
921+
853922 fn cdi_devices_config ( device_ids : & [ & str ] ) -> prost_types:: Struct {
854923 prost_types:: Struct {
855924 fields : std:: iter:: once ( (
@@ -1245,7 +1314,7 @@ mod tests {
12451314
12461315 fn test_driver ( socket_path : PathBuf ) -> PodmanComputeDriver {
12471316 let config = PodmanComputeConfig {
1248- socket_path,
1317+ socket_path : Some ( socket_path ) ,
12491318 stop_timeout_secs : 10 ,
12501319 ..PodmanComputeConfig :: default ( )
12511320 } ;
@@ -1453,7 +1522,7 @@ mod tests {
14531522 ) ] ,
14541523 ) ;
14551524 let config = PodmanComputeConfig {
1456- socket_path : socket_path. clone ( ) ,
1525+ socket_path : Some ( socket_path. clone ( ) ) ,
14571526 enable_bind_mounts : true ,
14581527 ..PodmanComputeConfig :: default ( )
14591528 } ;
0 commit comments