Source file remote_executable.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
open Core
open Poly
open Async
type 'a t =
{ host : string
; path : string
; host_key_checking : string list
}
[@@deriving fields ~getters]
let hostkey_checking_options opt =
match opt with
| None -> []
| Some `Ask -> [ "-o"; "StrictHostKeyChecking=ask" ]
| Some `No -> [ "-o"; "StrictHostKeyChecking=no" ]
| Some `Yes -> [ "-o"; "StrictHostKeyChecking=yes" ]
;;
let existing_on_host ~executable_path ?strict_host_key_checking host =
{ host
; path = executable_path
; host_key_checking = hostkey_checking_options strict_host_key_checking
}
;;
let copy_to_host ~executable_dir ?strict_host_key_checking host =
let our_basename = Filename.basename Sys.executable_name in
Process.run ~prog:"mktemp" ~args:[ "-u"; sprintf "%s.XXXXXXXX" our_basename ] ()
>>=? fun new_basename ->
let options = hostkey_checking_options strict_host_key_checking in
let path = String.strip (executable_dir ^/ new_basename) in
Process.run
~prog:"scp"
~args:(options @ [ Utils.our_binary (); sprintf "%s:%s" host path ])
()
>>|? Fn.const { host; path; host_key_checking = options }
;;
let delete executable =
Process.run
~prog:"ssh"
~args:(executable.host_key_checking @ [ executable.host; "rm"; executable.path ])
()
>>|? Fn.const ()
;;
let env_for_ssh env =
let env =
if am_running_test then ("TESTING_FRAMEWORK", "") :: env else env
in
let cheesy_escape str = Sexp.to_string (String.sexp_of_t str) in
List.map env ~f:(fun (key, data) -> key ^ "=" ^ cheesy_escape data)
;;
let run ?(assert_binary_hash = true) exec ~env ~args ~wrap =
let%bind.Deferred.Or_error () =
match assert_binary_hash with
| false -> Deferred.Or_error.ok_unit
| true ->
Utils.our_md5 ()
>>=? fun md5 ->
Process.run
~prog:"ssh"
~args:(exec.host_key_checking @ [ exec.host; "md5sum"; exec.path ])
()
>>=? fun remote_md5 ->
let remote_md5, _ = String.lsplit2_exn ~on:' ' remote_md5 in
if md5 <> remote_md5
then
Deferred.Or_error.errorf
"The remote executable %s:%s does not match the local executable"
exec.host
exec.path
else Deferred.Or_error.ok_unit
in
let { Prog_and_args.prog; args } = wrap { Prog_and_args.prog = exec.path; args } in
Process.create
~prog:"ssh"
~args:(exec.host_key_checking @ [ exec.host ] @ env_for_ssh env @ [ prog ] @ args)
()
;;