From a6c75e15b615451511b792f9db585277f2055671 Mon Sep 17 00:00:00 2001 From: Guillaume Bau Date: Tue, 6 May 2025 12:22:43 +0200 Subject: [PATCH] Tezt/Cloud: adds a new mode to enable ssh deployment --- tezt/lib_cloud/agent.ml | 5 +++-- tezt/lib_cloud/cli.ml | 7 +++++++ tezt/lib_cloud/cli.mli | 3 +++ tezt/lib_cloud/cloud.ml | 16 +++++++++++++--- tezt/lib_cloud/deployement.ml | 22 ++++++++++++++++------ tezt/lib_cloud/env.ml | 30 ++++++++++++++++++++++-------- tezt/lib_cloud/env.mli | 7 ++++++- tezt/lib_cloud/web.ml | 3 ++- 8 files changed, 72 insertions(+), 21 deletions(-) diff --git a/tezt/lib_cloud/agent.ml b/tezt/lib_cloud/agent.ml index 8561deb21565..86c0b9fece4f 100644 --- a/tezt/lib_cloud/agent.ml +++ b/tezt/lib_cloud/agent.ml @@ -17,11 +17,12 @@ module Configuration = struct let uri_of_docker_image docker_image = match (docker_image, Env.mode) with - | Types.Agent_configuration.Gcp {alias}, (`Cloud | `Host | `Orchestrator) -> + | ( Types.Agent_configuration.Gcp {alias}, + (`Cloud | `Host | `Orchestrator | `Ssh_host _) ) -> let* registry_uri = Env.registry_uri () in Lwt.return (Format.asprintf "%s/%s" registry_uri alias) | Gcp {alias}, `Localhost -> Lwt.return alias - | Octez_release _, (`Cloud | `Host | `Orchestrator) -> + | Octez_release _, (`Cloud | `Host | `Orchestrator | `Ssh_host _) -> let* registry_uri = Env.registry_uri () in Lwt.return (Format.asprintf "%s/octez" registry_uri) | Octez_release _, `Localhost -> Lwt.return "octez" diff --git a/tezt/lib_cloud/cli.ml b/tezt/lib_cloud/cli.ml index cac2031b1d77..cafc432a8e12 100644 --- a/tezt/lib_cloud/cli.ml +++ b/tezt/lib_cloud/cli.ml @@ -22,6 +22,13 @@ let localhost = ~description:"If set, the test is run locally" false +let ssh_host = + Clap.optional_string + ~section + ~long:"ssh-host" + ~description:"Whether to provision a non-gcp vm host via ssh" + () + let monitoring = Clap.flag ~section diff --git a/tezt/lib_cloud/cli.mli b/tezt/lib_cloud/cli.mli index cf80d28babd1..bd119f320766 100644 --- a/tezt/lib_cloud/cli.mli +++ b/tezt/lib_cloud/cli.mli @@ -143,3 +143,6 @@ val binaries_path : string Defaults to 300 Use 0 to disable log-rotation *) val log_rotation : int + +(** The hostname of the host accessed by ssh on which to deploy *) +val ssh_host : string option diff --git a/tezt/lib_cloud/cloud.ml b/tezt/lib_cloud/cloud.ml index bc3c979d24be..5efc413a40f9 100644 --- a/tezt/lib_cloud/cloud.ml +++ b/tezt/lib_cloud/cloud.ml @@ -470,7 +470,17 @@ let init_proxy ?(proxy_files = []) ?(proxy_args = []) deployement = in let process = let args = + (* remove "--ssh-host host" from the commande line *) + let rec filter_ssh acc args = + match args with + | [] -> List.rev acc + (* FIXME: remove proxy-localhost when agent name bug is fixed *) + | "--ssh-host" :: _host :: args -> + filter_ssh ("--proxy-localhost" :: "--proxy" :: acc) args + | arg :: args -> filter_ssh (arg :: acc) args + in let args = Sys.argv |> Array.to_list |> List.tl in + let args = filter_ssh [] args in args @ ["--localhost"; "--tezt-cloud"; Env.tezt_cloud] (* [--localhost] will be combined with --proxy, this enables to detect we want to run in [`Orchestrator]. @@ -552,7 +562,7 @@ let register ?proxy_files ?proxy_args ?vms ~__FILE__ ~title ~tags ?seed ?alerts future." ; match Env.mode with | `Localhost | `Cloud -> None - | `Host | `Orchestrator -> + | `Host | `Orchestrator | `Ssh_host (_, _) -> (* In Host mode, we want to run a deployment deploying the Proxy VM. In orchestrator mode, there is few initialisation steps needed. By using [Some []], we @@ -664,7 +674,7 @@ let register ?proxy_files ?proxy_args ?vms ~__FILE__ ~title ~tags ?seed ?alerts let* deployement = Deployement.deploy ~configurations in let* () = ensure_ready deployement in orchestrator ?alerts ?tasks deployement f - | `Host -> + | `Host | `Ssh_host _ -> (* The scenario is executed remotely. *) let* proxy_running = try_reattach () in if not proxy_running then @@ -709,7 +719,7 @@ let agents t = in [default_agent] | agents -> agents) - | `Host | `Cloud | `Localhost -> t.agents + | `Host | `Cloud | `Localhost | `Ssh_host _ -> t.agents let write_website t = match t.website with diff --git a/tezt/lib_cloud/deployement.ml b/tezt/lib_cloud/deployement.ml index 393d008758d3..0ef9614317b9 100644 --- a/tezt/lib_cloud/deployement.ml +++ b/tezt/lib_cloud/deployement.ml @@ -187,7 +187,7 @@ module Remote = struct let () = Log.report ~color:Log.Color.FG.green - "DNS registrered successfully: '%s'" + "DNS registered successfully: '%s'" domain in Lwt.return_unit @@ -355,8 +355,8 @@ module Ssh_host = struct in Lwt.return agent - let _deploy ~user ~host ~port ~(configurations : Agent.Configuration.t list) - () = + let deploy ~user ~host ~port ~(configurations : Agent.Configuration.t list) () + = let proxy_runner = Runner.create ~ssh_user:"root" ~ssh_port:port ~address:host () in @@ -428,9 +428,9 @@ module Ssh_host = struct let agents = proxy :: agents in Lwt.return {point = (user, host, port); agents} - let _agents t = t.agents + let agents t = t.agents - let _terminate {point; agents} = + let terminate {point; agents} = let _user, host, port = point in let* () = Lwt_list.iter_p @@ -596,7 +596,10 @@ module Localhost = struct else Lwt.return_unit end -type t = Remote of Remote.t | Localhost of Localhost.t +type t = + | Remote of Remote.t + | Ssh_host of Ssh_host.t + | Localhost of Localhost.t let deploy ~configurations = match Env.mode with @@ -610,15 +613,22 @@ let deploy ~configurations = let* remote = Remote.deploy ~proxy:true ~configurations in Lwt.return (Remote remote) | `Orchestrator -> assert false + | `Ssh_host (host, port) -> + let* host = + Ssh_host.deploy ~user:(Sys.getenv "USER") ~host ~port ~configurations () + in + Lwt.return (Ssh_host host) let agents t = match t with | Remote remote -> Remote.agents remote | Localhost localhost -> Localhost.agents localhost + | Ssh_host remote -> Ssh_host.agents remote let terminate ?exn t = match t with | Remote remote -> Remote.terminate ?exn remote | Localhost localhost -> Localhost.terminate ?exn localhost + | Ssh_host remote -> Ssh_host.terminate remote let of_agents agents = Remote {agents} diff --git a/tezt/lib_cloud/env.ml b/tezt/lib_cloud/env.ml index 908e6f5815e0..2f9f4a4f1346 100644 --- a/tezt/lib_cloud/env.ml +++ b/tezt/lib_cloud/env.ml @@ -12,6 +12,25 @@ let tezt_cloud = (* This is a lazy value to be sure that this is evaluated only inside a Tezt test. *) match Sys.getenv_opt "TEZT_CLOUD" with None -> "" | Some value -> value) +let mode = + match (Cli.localhost, Cli.proxy, Cli.ssh_host) with + | true, true, None -> `Orchestrator + | true, false, None -> `Localhost + | false, true, None -> `Host + | false, false, None -> `Cloud + | true, _, Some _ | _, true, Some _ -> + Test.fail + "Unexpected combination of options: ssh_host and (proxy or localhost)" + | _, _, Some endpoint -> + let uri = Uri.of_string (Format.asprintf "tcp://%s" endpoint) in + let host = + match Uri.host uri with + | None -> Test.fail "No valid hostname specified: %s" endpoint + | Some host -> host + in + let port = Option.value ~default:22 (Uri.port uri) in + `Ssh_host (host, port) + let ssh_private_key_filename ?(home = Sys.getenv "HOME") () = home // ".ssh" // Format.asprintf "%s-tf" tezt_cloud @@ -19,13 +38,6 @@ let ssh_public_key_filename ?home () = let ssh_key = ssh_private_key_filename ?home () in Format.asprintf "%s.pub" ssh_key -let mode = - match (Cli.localhost, Cli.proxy) with - | true, true -> `Orchestrator - | true, false -> `Localhost - | false, true -> `Host - | false, false -> `Cloud - let prometheus = Cli.prometheus let prometheus_export = Cli.prometheus_export @@ -133,6 +145,7 @@ let init () = ( with_open_out pidfile @@ fun fd -> output_string fd (Format.asprintf "%d\n" pid) ) ; Lwt.return_unit + | `Ssh_host _ -> Lwt.return_unit | `Host | `Cloud -> let* project_id = project_id () in Log.info "Initializing docker registry..." ; @@ -222,7 +235,8 @@ let dns_domains () = match domain with | None -> Lwt.return Cli.dns_domains | Some domain -> Lwt.return (domain :: Cli.dns_domains)) - | `Orchestrator | `Localhost | `Cloud -> Lwt.return Cli.dns_domains + | `Orchestrator | `Localhost | `Cloud | `Ssh_host _ -> + Lwt.return Cli.dns_domains in (* A fully-qualified domain name requires to end with a dot. However, the usage tends to omit this final dot. Because having a diff --git a/tezt/lib_cloud/env.mli b/tezt/lib_cloud/env.mli index a507c48fe41c..d5376d67e575 100644 --- a/tezt/lib_cloud/env.mli +++ b/tezt/lib_cloud/env.mli @@ -31,8 +31,13 @@ val ssh_public_key_filename : ?home:string -> unit -> string - [`Host]: This mode is run by the host machine that initializes the orchestrator running on a VM. + + - [`Ssh_host (host, port)]: This mode is similar to the Orchestrator mode, but + on a non-gcp vm. Its purpose is to make an initial provisioning + of docker if it is not setup. *) -val mode : [`Localhost | `Cloud | `Orchestrator | `Host] +val mode : + [`Localhost | `Ssh_host of string * int | `Cloud | `Orchestrator | `Host] (** Equivalent to [Cli.prometheus]. *) val prometheus : bool diff --git a/tezt/lib_cloud/web.ml b/tezt/lib_cloud/web.ml index 5a830cb7bed7..a4fd37446182 100644 --- a/tezt/lib_cloud/web.ml +++ b/tezt/lib_cloud/web.ml @@ -24,7 +24,8 @@ let pp_docker_image fmt = function let domain agents = match Env.mode with - | `Orchestrator -> Proxy.get_agent agents |> Agent.point |> Option.get |> fst + | `Orchestrator | `Ssh_host _ -> + Proxy.get_agent agents |> Agent.point |> Option.get |> fst | `Host | `Localhost | `Cloud -> "localhost" let string_docker_command agent = -- GitLab