@@ -41,6 +41,15 @@ class SSHDriver(CommandMixin, Driver, CommandProtocol, FileTransferProtocol):
41
41
def __attrs_post_init__ (self ):
42
42
super ().__attrs_post_init__ ()
43
43
self ._keepalive = None
44
+ self ._ssh = self ._get_tool ("ssh" )
45
+ self ._scp = self ._get_tool ("scp" )
46
+ self ._sshfs = self ._get_tool ("sshfs" )
47
+ self ._rsync = self ._get_tool ("rsync" )
48
+
49
+ def _get_tool (self , name ):
50
+ if self .target .env :
51
+ return self .target .env .config .get_tool (name )
52
+ return name
44
53
45
54
def _get_username (self ):
46
55
"""Get the username from this class or from NetworkService"""
@@ -105,7 +114,7 @@ def _start_own_master_once(self, timeout):
105
114
self .tmpdir , f'control-{ self .networkservice .address } '
106
115
)
107
116
108
- args = ["ssh" , "-f" , * self .ssh_prefix , "-x" , "-o" , f"ConnectTimeout={ timeout } " ,
117
+ args = [self . _ssh , "-f" , * self .ssh_prefix , "-x" , "-o" , f"ConnectTimeout={ timeout } " ,
109
118
"-o" , "ControlPersist=300" , "-o" ,
110
119
"UserKnownHostsFile=/dev/null" , "-o" , "StrictHostKeyChecking=no" ,
111
120
"-o" , "ServerAliveInterval=15" , "-MN" , "-S" , control .replace ('%' , '%%' ), "-p" ,
@@ -203,7 +212,7 @@ def _run(self, cmd, codec="utf-8", decodeerrors="strict", timeout=None):
203
212
if not self ._check_keepalive ():
204
213
raise ExecutionError ("Keepalive no longer running" )
205
214
206
- complete_cmd = ["ssh" , "-x" , * self .ssh_prefix ,
215
+ complete_cmd = [self . _ssh , "-x" , * self .ssh_prefix ,
207
216
"-p" , str (self .networkservice .port ), "-l" , self ._get_username (),
208
217
self .networkservice .address
209
218
] + cmd .split (" " )
@@ -238,7 +247,7 @@ def interact(self, cmd=None):
238
247
if not self ._check_keepalive ():
239
248
raise ExecutionError ("Keepalive no longer running" )
240
249
241
- complete_cmd = ["ssh" , "-x" , * self .ssh_prefix ,
250
+ complete_cmd = [self . _ssh , "-x" , * self .ssh_prefix ,
242
251
"-t" ,
243
252
self .networkservice .address
244
253
]
@@ -252,7 +261,7 @@ def interact(self, cmd=None):
252
261
253
262
@contextlib .contextmanager
254
263
def _forward (self , forward ):
255
- cmd = ["ssh" , * self .ssh_prefix ,
264
+ cmd = [self . _ssh , * self .ssh_prefix ,
256
265
"-O" , "forward" , forward ,
257
266
self .networkservice .address
258
267
]
@@ -261,7 +270,7 @@ def _forward(self, forward):
261
270
try :
262
271
yield
263
272
finally :
264
- cmd = ["ssh" , * self .ssh_prefix ,
273
+ cmd = [self . _ssh , * self .ssh_prefix ,
265
274
"-O" , "cancel" , forward ,
266
275
self .networkservice .address
267
276
]
@@ -361,7 +370,8 @@ def scp(self, *, src, dst):
361
370
if dst .startswith (':' ):
362
371
dst = '_' + dst
363
372
364
- complete_cmd = ["scp" ,
373
+ complete_cmd = [self ._scp ,
374
+ "-S" , self ._ssh ,
365
375
"-F" , "none" ,
366
376
"-o" , f"ControlPath={ self .control .replace ('%' , '%%' )} " ,
367
377
src , dst ,
@@ -391,12 +401,12 @@ def rsync(self, *, src, dst, extra=[]):
391
401
if dst .startswith (':' ):
392
402
dst = '_' + dst
393
403
394
- ssh_cmd = ["ssh" ,
404
+ ssh_cmd = [self . _ssh ,
395
405
"-F" , "none" ,
396
406
"-o" , f"ControlPath={ self .control .replace ('%' , '%%' )} " ,
397
407
]
398
408
399
- complete_cmd = ["rsync" ,
409
+ complete_cmd = [self . _rsync ,
400
410
"-v" ,
401
411
f"--rsh={ ' ' .join (ssh_cmd )} " ,
402
412
"-rlpt" , # --recursive --links --perms --times
@@ -417,7 +427,7 @@ def sshfs(self, *, path, mountpoint):
417
427
if not self ._check_keepalive ():
418
428
raise ExecutionError ("Keepalive no longer running" )
419
429
420
- complete_cmd = ["sshfs" ,
430
+ complete_cmd = [self . _sshfs ,
421
431
"-F" , "none" ,
422
432
"-f" ,
423
433
"-o" , f"ControlPath={ self .control .replace ('%' , '%%' )} " ,
@@ -445,7 +455,7 @@ def get_status(self):
445
455
446
456
@cached_property
447
457
def _ssh_version (self ):
448
- version = subprocess .run (["ssh" , "-V" ], capture_output = True , text = True )
458
+ version = subprocess .run ([self . _ssh , "-V" ], capture_output = True , text = True )
449
459
version = re .match (r"^OpenSSH_(\d+)\.(\d+)" , version .stderr )
450
460
return tuple (int (x ) for x in version .groups ())
451
461
@@ -472,7 +482,8 @@ def _scp_supports_explicit_scp_mode(self):
472
482
@step (args = ['filename' , 'remotepath' ])
473
483
def put (self , filename , remotepath = '' ):
474
484
transfer_cmd = [
475
- "scp" ,
485
+ self ._scp ,
486
+ "-S" , self ._ssh ,
476
487
* self .ssh_prefix ,
477
488
"-P" , str (self .networkservice .port ),
478
489
"-r" ,
@@ -502,7 +513,8 @@ def put(self, filename, remotepath=''):
502
513
@step (args = ['filename' , 'destination' ])
503
514
def get (self , filename , destination = "." ):
504
515
transfer_cmd = [
505
- "scp" ,
516
+ self ._scp ,
517
+ "-S" , self ._ssh ,
506
518
* self .ssh_prefix ,
507
519
"-P" , str (self .networkservice .port ),
508
520
"-r" ,
@@ -530,7 +542,7 @@ def get(self, filename, destination="."):
530
542
531
543
def _cleanup_own_master (self ):
532
544
"""Exit the controlmaster and delete the tmpdir"""
533
- complete_cmd = f"ssh -x -o ControlPath={ self .control .replace ('%' , '%%' )} -O exit -p { self .networkservice .port } -l { self ._get_username ()} { self .networkservice .address } " .split (' ' ) # pylint: disable=line-too-long
545
+ complete_cmd = f"{ self . _ssh } -x -o ControlPath={ self .control .replace ('%' , '%%' )} -O exit -p { self .networkservice .port } -l { self ._get_username ()} { self .networkservice .address } " .split (' ' ) # pylint: disable=line-too-long
534
546
res = subprocess .call (
535
547
complete_cmd ,
536
548
stdin = subprocess .DEVNULL ,
@@ -547,7 +559,7 @@ def _cleanup_own_master(self):
547
559
548
560
def _start_keepalive (self ):
549
561
"""Starts a keepalive connection via the own or external master."""
550
- args = ["ssh" , * self .ssh_prefix , self .networkservice .address , "cat" ]
562
+ args = [self . _ssh , * self .ssh_prefix , self .networkservice .address , "cat" ]
551
563
552
564
assert self ._keepalive is None
553
565
self ._keepalive = subprocess .Popen (
0 commit comments