From a7e2b5d5c081eb12b5634767d67186d53f34acb7 Mon Sep 17 00:00:00 2001 From: Guillaume Bau Date: Mon, 5 May 2025 17:14:50 +0200 Subject: [PATCH 1/4] Tezt/Cloud/Docker: allow 'rm' to run with a tezt-runner --- tezt/lib_cloud/docker.ml | 8 +++++++- tezt/lib_cloud/docker.mli | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tezt/lib_cloud/docker.ml b/tezt/lib_cloud/docker.ml index f30fa419fc74..95be0206e0c7 100644 --- a/tezt/lib_cloud/docker.ml +++ b/tezt/lib_cloud/docker.ml @@ -78,7 +78,13 @@ let run ?(rm = false) ?name ?network ?publish_ports image args = let kill container_name = Process.spawn ~color "docker" ["kill"; container_name] -let rm container_name = Process.spawn ~color "docker" ["rm"; container_name] +let rm ?runner ?(force = false) container_name = + Log.info "Docker.rm '%s'" container_name ; + Process.spawn + ?runner + ~color + "docker" + (["rm"] @ (if force then ["--force"] else []) @ [container_name]) let cp container_name ~kind ~source ~destination = match kind with diff --git a/tezt/lib_cloud/docker.mli b/tezt/lib_cloud/docker.mli index 0b5cc4970f72..95b0d7c78d38 100644 --- a/tezt/lib_cloud/docker.mli +++ b/tezt/lib_cloud/docker.mli @@ -61,7 +61,7 @@ val run : val kill : string -> Process.t (** [rm] is an alias for [docker rm]. *) -val rm : string -> Process.t +val rm : ?runner:Runner.t -> ?force:bool -> string -> Process.t (** [cp] is an alias for [docker cp]. *) val cp : -- GitLab From ba0bfba55a1cf9729499438c3fc0360036d324a4 Mon Sep 17 00:00:00 2001 From: Guillaume Bau Date: Mon, 5 May 2025 17:15:59 +0200 Subject: [PATCH 2/4] Tezt/Cloud/Docker: allow 'run' to be used with a runner --- tezt/lib_cloud/docker.ml | 16 ++++++++++++++-- tezt/lib_cloud/docker.mli | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tezt/lib_cloud/docker.ml b/tezt/lib_cloud/docker.ml index 95be0206e0c7..67f399ce2970 100644 --- a/tezt/lib_cloud/docker.ml +++ b/tezt/lib_cloud/docker.ml @@ -55,7 +55,8 @@ let pull ?image_name ?alias ?(tag = "latest") ~registry_uri () = let network ~command ~network_name = Process.spawn ~color "docker" (["network"] @ [command] @ [network_name]) -let run ?(rm = false) ?name ?network ?publish_ports image args = +let run ?runner ?(rm = false) ?name ?network ?publish_ports ?volumes image args + = let publish_ports = match publish_ports with | None -> [] @@ -67,12 +68,23 @@ let run ?(rm = false) ?name ?network ?publish_ports image args = in let name = match name with None -> [] | Some name -> ["--name"; name] in let rm = if rm then ["--rm"] else [] in + let volumes = + match volumes with + | None -> [] + | Some volumes -> + let arg_of_volume (host, container) = + ["-v"; Format.asprintf "%s:%s" host container] + in + List.map arg_of_volume volumes |> List.flatten + in (* [init] can be used to ensure signals are forwarded properly to the entrypoint run by the container. *) Process.spawn + ?runner ~color "docker" - (["run"] @ rm @ name @ macos_platform_arg @ network @ publish_ports + (["run"] @ rm @ name @ macos_platform_arg @ volumes @ network + @ publish_ports @ [Format.asprintf "%s" image] @ args) diff --git a/tezt/lib_cloud/docker.mli b/tezt/lib_cloud/docker.mli index 95b0d7c78d38..0b887c9ae092 100644 --- a/tezt/lib_cloud/docker.mli +++ b/tezt/lib_cloud/docker.mli @@ -49,10 +49,12 @@ val network : command:string -> network_name:string -> Process.t (** [run] is an alias for [docker run]. *) val run : + ?runner:Runner.t -> ?rm:bool -> ?name:string -> ?network:string -> ?publish_ports:string * string * string * string -> + ?volumes:(string * string) list -> string -> string list -> Process.t -- GitLab From b5c11699531adffa8b17b8f361809ccfd7512982 Mon Sep 17 00:00:00 2001 From: Guillaume Bau Date: Tue, 6 May 2025 11:40:04 +0200 Subject: [PATCH 3/4] Tezt/Cloud/Docker: adds detach argument --- tezt/lib_cloud/docker.ml | 7 ++++--- tezt/lib_cloud/docker.mli | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tezt/lib_cloud/docker.ml b/tezt/lib_cloud/docker.ml index 67f399ce2970..4f18d61f637a 100644 --- a/tezt/lib_cloud/docker.ml +++ b/tezt/lib_cloud/docker.ml @@ -55,8 +55,8 @@ let pull ?image_name ?alias ?(tag = "latest") ~registry_uri () = let network ~command ~network_name = Process.spawn ~color "docker" (["network"] @ [command] @ [network_name]) -let run ?runner ?(rm = false) ?name ?network ?publish_ports ?volumes image args - = +let run ?runner ?(rm = false) ?name ?(detach = false) ?network ?publish_ports + ?volumes image args = let publish_ports = match publish_ports with | None -> [] @@ -68,6 +68,7 @@ let run ?runner ?(rm = false) ?name ?network ?publish_ports ?volumes image args in let name = match name with None -> [] | Some name -> ["--name"; name] in let rm = if rm then ["--rm"] else [] in + let detach = if detach then ["-d"] else [] in let volumes = match volumes with | None -> [] @@ -83,7 +84,7 @@ let run ?runner ?(rm = false) ?name ?network ?publish_ports ?volumes image args ?runner ~color "docker" - (["run"] @ rm @ name @ macos_platform_arg @ volumes @ network + (["run"] @ detach @ rm @ name @ macos_platform_arg @ volumes @ network @ publish_ports @ [Format.asprintf "%s" image] @ args) diff --git a/tezt/lib_cloud/docker.mli b/tezt/lib_cloud/docker.mli index 0b887c9ae092..1c48b3fcc8b0 100644 --- a/tezt/lib_cloud/docker.mli +++ b/tezt/lib_cloud/docker.mli @@ -52,6 +52,7 @@ val run : ?runner:Runner.t -> ?rm:bool -> ?name:string -> + ?detach:bool -> ?network:string -> ?publish_ports:string * string * string * string -> ?volumes:(string * string) list -> -- GitLab From b7bfb61ef52d4aed1e727a9b8e72ea86c2f840ed Mon Sep 17 00:00:00 2001 From: Guillaume Bau Date: Mon, 5 May 2025 17:35:55 +0200 Subject: [PATCH 4/4] Tezt/Cloud: adds a new default proxy deployment on a ssh host The host is expected to be reachable connecting with a root user, the machine must have been provisioned correctly --- tezt/lib_cloud/deployement.ml | 148 ++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/tezt/lib_cloud/deployement.ml b/tezt/lib_cloud/deployement.ml index 38484aee89fc..393d008758d3 100644 --- a/tezt/lib_cloud/deployement.ml +++ b/tezt/lib_cloud/deployement.ml @@ -296,6 +296,154 @@ module Remote = struct Lwt.return_unit) end +(* Deployment on a SSH reachable host. At this moment, it is expected to be a + debian bookworm, and apt must be executable by the user connecting with sudo. + At this moment, this deployment launches a proxy mode docker. *) +module Ssh_host = struct + type t = {point : string * string * int; agents : Agent.t list} + + let deploy_proxy runner = + let configuration = Proxy.make_config () in + let next_available_port = + let cpt = ref 30_000 in + fun () -> + incr cpt ; + !cpt + in + let name = configuration.name in + let* docker_image = + Agent.Configuration.uri_of_docker_image configuration.vm.docker_image + in + (* Remove any existing proxy first *) + let* () = Docker.rm ~runner ~force:true name |> Process.check in + (* Prepare the arguments for docker run *) + let ssh_listening_port = next_available_port () in + let guest_port = string_of_int ssh_listening_port in + let publish_ports = (guest_port, guest_port, guest_port, guest_port) in + let volumes = + [ + ("/var/run/docker.sock", "/var/run/docker.sock"); + ("/tmp/prometheus", "/tmp/prometheus"); + ("/tmp/website", "/tmp/website"); + ("/tmp/grafana", "/tmp/grafana"); + ("/tmp/alert_manager", "/tmp/alert_manager"); + ("/tmp/otel", "/tmp/otel"); + ] + in + let* () = + Docker.run + ~runner + ~rm:true + ~detach:true + ~network:"host" + ~volumes + ~publish_ports + ~name + docker_image + ["-D"; "-p"; guest_port] + |> Process.check + in + let agent = + Agent.make + ~vm_name:None + ~configuration + ~next_available_port + ~point:(Runner.address (Some runner), ssh_listening_port) + ~ssh_id:(Env.ssh_private_key_filename ()) + ~process_monitor:None + () + in + Lwt.return agent + + let _deploy ~user ~host ~port ~(configurations : Agent.Configuration.t list) + () = + let proxy_runner = + Runner.create ~ssh_user:"root" ~ssh_port:port ~address:host () + in + (* Deploys the proxy *) + let* proxy = deploy_proxy proxy_runner in + (* Deploys all agents *) + let* agents = + Lwt_list.mapi_p + (fun i (configuration : Agent.Configuration.t) -> + let* docker_image = + Agent.Configuration.uri_of_docker_image + configuration.vm.docker_image + in + let ssh_port = Agent.next_available_port proxy in + (* FIXME move this constants elsewhere *) + let base_port = 30_050 in + let range = 50 in + let runner = + Runner.create ~ssh_user:user ~ssh_port:port ~address:host () + in + let publish_ports = + ( string_of_int (base_port + (i * range)), + string_of_int (base_port + ((i + 1) * range) - 1), + string_of_int (base_port + (i * range)), + string_of_int (base_port + ((i + 1) * range) - 1) ) + in + let* () = + Docker.run + ~runner + ~detach:true + ~publish_ports + ~network:"host" + ~name:configuration.name + docker_image + [ + "--entrypoint"; + "/usr/bin/sshd"; + "-D"; + "-p"; + string_of_int ssh_port; + "-e"; + ] + |> Process.check + in + let () = + Log.warn + "Deployed agent: %s on (%s, %d)" + configuration.name + host + ssh_port + in + let agent = + Agent.make + ~vm_name:None + ~configuration + ~next_available_port: + (let cpt = ref (base_port + (i * range)) in + fun () -> + incr cpt ; + !cpt) + ~process_monitor:None + ~point:(host, ssh_port) + ~ssh_id:(Env.ssh_private_key_filename ()) + () + in + Lwt.return agent) + configurations + in + let agents = proxy :: agents in + Lwt.return {point = (user, host, port); agents} + + let _agents t = t.agents + + let _terminate {point; agents} = + let _user, host, port = point in + let* () = + Lwt_list.iter_p + (fun agent -> + let name = Agent.name agent in + let runner = Runner.create ~ssh_port:port ~address:host () in + let* _ = Docker.rm ~runner name |> Process.check in + Lwt.return_unit) + agents + in + Lwt.return_unit +end + (* Infrastructure to deploy locally using Docker *) module Localhost = struct type t = { -- GitLab