From 74556e7c71f68b2ca742995f9202105bf168feb9 Mon Sep 17 00:00:00 2001 From: Guillaume Genestier Date: Fri, 25 Jul 2025 14:43:24 +0200 Subject: [PATCH 1/4] Tezt/Cloud/DAL: Configuration file restricted to the scenario settings --- manifest/product_tezt_cloud_tests.ml | 1 + tezt/tests/cloud/baker_helpers.ml | 2 +- tezt/tests/cloud/baker_helpers.mli | 2 +- tezt/tests/cloud/dal.ml | 29 +- tezt/tests/cloud/dal_node_helpers.mli | 4 +- tezt/tests/cloud/dal_reverse_proxy.mli | 2 +- tezt/tests/cloud/dune | 3 +- tezt/tests/cloud/echo_rollup.mli | 2 +- tezt/tests/cloud/etherlink_helpers.mli | 2 +- tezt/tests/cloud/network.ml | 112 ++++- tezt/tests/cloud/network.mli | 10 +- tezt/tests/cloud/scenarios_cli.ml | 405 +++++++++++-------- tezt/tests/cloud/scenarios_configuration.ml | 306 ++++++++++++++ tezt/tests/cloud/scenarios_configuration.mli | 82 ++++ tezt/tests/cloud/yes_crypto.ml | 2 +- tezt/tests/cloud/yes_crypto.mli | 2 +- 16 files changed, 763 insertions(+), 203 deletions(-) create mode 100644 tezt/tests/cloud/scenarios_configuration.ml create mode 100644 tezt/tests/cloud/scenarios_configuration.mli diff --git a/manifest/product_tezt_cloud_tests.ml b/manifest/product_tezt_cloud_tests.ml index 34011a884de3..dd525d6dd219 100644 --- a/manifest/product_tezt_cloud_tests.ml +++ b/manifest/product_tezt_cloud_tests.ml @@ -24,6 +24,7 @@ let _main = tezt_tezos |> open_ |> open_ ~m:"Runnable.Syntax"; tezt_cloud |> open_; tezt_etherlink; + octez_stdlib_unix; ] ~release_status:Unreleased ~with_macos_security_framework:true diff --git a/tezt/tests/cloud/baker_helpers.ml b/tezt/tests/cloud/baker_helpers.ml index 1b18149510ac..36f1317cd797 100644 --- a/tezt/tests/cloud/baker_helpers.ml +++ b/tezt/tests/cloud/baker_helpers.ml @@ -7,7 +7,7 @@ (*****************************************************************************) open Agent_kind -open Scenarios_cli +open Scenarios_configuration open Scenarios_helpers open Tezos open Yes_crypto diff --git a/tezt/tests/cloud/baker_helpers.mli b/tezt/tests/cloud/baker_helpers.mli index bbf65daee85f..f2d7c4753a58 100644 --- a/tezt/tests/cloud/baker_helpers.mli +++ b/tezt/tests/cloud/baker_helpers.mli @@ -37,7 +37,7 @@ val init_bakers : bakers:string list -> stake:int list Lwt.t -> data_dir:string option -> - simulate_network:Scenarios_cli.network_simulation_config -> + simulate_network:Scenarios_configuration.network_simulation_config -> external_rpc:bool -> network:Network.t -> snapshot:Snapshot_helpers.t -> diff --git a/tezt/tests/cloud/dal.ml b/tezt/tests/cloud/dal.ml index 8d93c9d215cd..87979c08cfa8 100644 --- a/tezt/tests/cloud/dal.ml +++ b/tezt/tests/cloud/dal.ml @@ -32,7 +32,7 @@ type configuration = { with_dal : bool; stake : int list Lwt.t; bakers : string list; (* unencrypted secret keys *) - stake_machine_type : string list option; + stake_machine_type : string list; dal_node_producers : int list; (* slot indices *) observer_slot_indices : int list; observer_pkhs : string list; @@ -43,7 +43,7 @@ type configuration = { echo_rollup : bool; disconnect : (int * int) option; network : Network.t; - simulate_network : Cli.network_simulation_config; + simulate_network : Scenarios_configuration.network_simulation_config; snapshot : Snapshot_helpers.t; bootstrap : bool; teztale : bool; @@ -447,8 +447,8 @@ let round_robin_split m lst = (fun idx x -> let bucket = idx mod m in buckets.(bucket) <- x :: buckets.(bucket)) - (List.rev lst) ; - Array.to_list buckets |> List.rev + lst ; + Array.to_list buckets |> List.map List.rev let init_sandbox_and_activate_protocol cloud (configuration : configuration) ?(etherlink_configuration : @@ -1188,7 +1188,7 @@ let yes_wallet_exe = Uses.path Constant.yes_wallet let parse_stake_arg ~stake_arg ~simulation_arg = let open Network in match simulation_arg with - | Cli.Disabled -> ( + | Scenarios_configuration.Disabled -> ( match stake_arg with | Custom distrib -> return distrib | Mimic {network; max_nb_bakers} -> @@ -1385,7 +1385,7 @@ let register (module Cli : Scenarios_cli.Dal) = toplog "Parsing CLI done" ; let baker_daemon_count = match simulate_network with - | Scenarios_cli.Disabled -> 0 + | Scenarios_configuration.Disabled -> 0 | Scatter (_selected_baker_count, baker_daemon_count) -> baker_daemon_count | Map ( _selected_baker_count, @@ -1444,17 +1444,12 @@ let register (module Cli : Scenarios_cli.Dal) = match agent_kind with | Bootstrap -> default_vm_configuration ~name | Baker i -> ( - match configuration.stake_machine_type with - | None -> default_vm_configuration ~name - | Some list -> ( - try - let machine_type = List.nth list i in - Agent.Configuration.make - ?docker_image - ~machine_type - ~name - () - with _ -> default_vm_configuration ~name)) + try + let machine_type = + List.nth configuration.stake_machine_type i + in + Agent.Configuration.make ?docker_image ~machine_type ~name () + with _ -> default_vm_configuration ~name) | Producer _ -> let machine_type = configuration.producer_machine_type in Agent.Configuration.make ?docker_image ?machine_type ~name () diff --git a/tezt/tests/cloud/dal_node_helpers.mli b/tezt/tests/cloud/dal_node_helpers.mli index 1edfdb1bc9ee..d8589f4d37cd 100644 --- a/tezt/tests/cloud/dal_node_helpers.mli +++ b/tezt/tests/cloud/dal_node_helpers.mli @@ -73,7 +73,7 @@ val init_producer_accounts : val init_producer : Cloud.t -> data_dir:string option -> - simulate_network:Scenarios_cli.network_simulation_config -> + simulate_network:Scenarios_configuration.network_simulation_config -> external_rpc:bool -> network:Network.t -> snapshot:Snapshot_helpers.t -> @@ -115,7 +115,7 @@ val producers_not_ready : producers:producer list -> bool val init_observer : Cloud.t -> data_dir:string option -> - simulate_network:Scenarios_cli.network_simulation_config -> + simulate_network:Scenarios_configuration.network_simulation_config -> external_rpc:bool -> network:Network.t -> snapshot:Snapshot_helpers.t -> diff --git a/tezt/tests/cloud/dal_reverse_proxy.mli b/tezt/tests/cloud/dal_reverse_proxy.mli index 0bce05e01993..a714bca23d2c 100644 --- a/tezt/tests/cloud/dal_reverse_proxy.mli +++ b/tezt/tests/cloud/dal_reverse_proxy.mli @@ -31,7 +31,7 @@ val init_dal_reverse_proxy_observers : ppx_profiling:bool -> ppx_profiling_backends:string list -> memtrace:bool -> - simulate_network:Scenarios_cli.network_simulation_config -> + simulate_network:Scenarios_configuration.network_simulation_config -> name_of:(int -> string) -> default_endpoint:string option -> node_p2p_endpoint:string -> diff --git a/tezt/tests/cloud/dune b/tezt/tests/cloud/dune index 40f3df964c65..b3e7187547c1 100644 --- a/tezt/tests/cloud/dune +++ b/tezt/tests/cloud/dune @@ -9,7 +9,8 @@ octez-libs.tezt-wrapper tezt-tezos tezt-cloud - tezt_etherlink) + tezt_etherlink + octez-libs.stdlib-unix) (link_flags (:standard) (:include %{workspace_root}/macos-link-flags.sexp)) diff --git a/tezt/tests/cloud/echo_rollup.mli b/tezt/tests/cloud/echo_rollup.mli index 89e779ba7adb..88836c60d1eb 100644 --- a/tezt/tests/cloud/echo_rollup.mli +++ b/tezt/tests/cloud/echo_rollup.mli @@ -28,7 +28,7 @@ val init_echo_rollup_account : val init_echo_rollup : Cloud.t -> data_dir:string option -> - simulate_network:Scenarios_cli.network_simulation_config -> + simulate_network:Scenarios_configuration.network_simulation_config -> external_rpc:bool -> network:Network.t -> snapshot:Snapshot_helpers.t -> diff --git a/tezt/tests/cloud/etherlink_helpers.mli b/tezt/tests/cloud/etherlink_helpers.mli index 5360f417c845..3b615837dd58 100644 --- a/tezt/tests/cloud/etherlink_helpers.mli +++ b/tezt/tests/cloud/etherlink_helpers.mli @@ -47,7 +47,7 @@ val init_etherlink_operators : DAL if enabled and a configurable number of producers. *) val init_etherlink : data_dir:string option -> - simulate_network:Scenarios_cli.network_simulation_config -> + simulate_network:Scenarios_configuration.network_simulation_config -> external_rpc:bool -> network:Network.t -> snapshot:Snapshot_helpers.t -> diff --git a/tezt/tests/cloud/network.ml b/tezt/tests/cloud/network.ml index a5564192f568..c124fde40d80 100644 --- a/tezt/tests/cloud/network.ml +++ b/tezt/tests/cloud/network.ml @@ -14,12 +14,122 @@ type public = | `Rionet | `Seoulnet ] -type t = [public | `Sandbox] +type t = [`Sandbox | public] + +let public_encoding = + let open Data_encoding in + union + [ + case + (Tag 2) + ~title:"mainnet" + empty + (function `Mainnet -> Some () | _ -> None) + (fun () -> `Mainnet); + case + (Tag 3) + ~title:"ghostnet" + empty + (function `Ghostnet -> Some () | _ -> None) + (fun () -> `Ghostnet); + case + (Tag 4) + ~title:"nextnet" + string + (function `Nextnet date -> Some date | _ -> None) + (fun date -> `Nextnet date); + case + (Tag 5) + ~title:"weeklynet" + string + (function `Weeklynet date -> Some date | _ -> None) + (fun date -> `Weeklynet date); + case + (Tag 6) + ~title:"rionet" + empty + (function `Rionet -> Some () | _ -> None) + (fun () -> `Rionet); + case + (Tag 7) + ~title:"seoulnet" + empty + (function `Seoulnet -> Some () | _ -> None) + (fun () -> `Seoulnet); + ] + +let encoding = + let open Data_encoding in + union + [ + case + (Tag 1) + ~title:"sandbox" + empty + (function `Sandbox -> Some () | _ -> None) + (fun () -> `Sandbox); + case + (Tag 2) + ~title:"mainnet" + empty + (function `Mainnet -> Some () | _ -> None) + (fun () -> `Mainnet); + case + (Tag 3) + ~title:"ghostnet" + empty + (function `Ghostnet -> Some () | _ -> None) + (fun () -> `Ghostnet); + case + (Tag 4) + ~title:"nextnet" + string + (function `Nextnet date -> Some date | _ -> None) + (fun date -> `Nextnet date); + case + (Tag 5) + ~title:"weeklynet" + string + (function `Weeklynet date -> Some date | _ -> None) + (fun date -> `Weeklynet date); + case + (Tag 6) + ~title:"rionet" + empty + (function `Rionet -> Some () | _ -> None) + (fun () -> `Rionet); + case + (Tag 7) + ~title:"seoulnet" + empty + (function `Seoulnet -> Some () | _ -> None) + (fun () -> `Seoulnet); + ] type stake_repartition = | Custom of int list | Mimic of {network : public; max_nb_bakers : int option} +let stake_repartition_encoding = + let open Data_encoding in + union + [ + case + (Tag 1) + ~title:"custom" + (list int31) + (function Custom l -> Some l | _ -> None) + (fun l -> Custom l); + case + (Tag 2) + ~title:"mimic" + (obj2 (req "network" public_encoding) (opt "max_nb_bakers" int31)) + (function + | Mimic {network; max_nb_bakers} -> Some (network, max_nb_bakers) + | _ -> None) + (fun (network, max_nb_bakers) -> Mimic {network; max_nb_bakers}); + ] + let to_public = function | `Sandbox -> failwith "Sandbox is not public" | #public as p -> p diff --git a/tezt/tests/cloud/network.mli b/tezt/tests/cloud/network.mli index f679f521b28a..fd31070bb349 100644 --- a/tezt/tests/cloud/network.mli +++ b/tezt/tests/cloud/network.mli @@ -23,14 +23,18 @@ type public = type t = [public | `Sandbox] +(** ["mainnet" | "ghostnet" | "rionet" | "seoulnet" | "nextnet-%s" | "weeklynet-%s" | "sandbox"] *) +val to_string : [< t] -> string + +val encoding : t Data_encoding.t + type stake_repartition = | Custom of int list | Mimic of {network : public; max_nb_bakers : int option} -val to_public : t -> public +val stake_repartition_encoding : stake_repartition Data_encoding.t -(** ["mainnet" | "ghostnet" | "rionet" | "seoulnet" | "nextnet-%s" | "weeklynet-%s" | "sandbox"] *) -val to_string : [< t] -> string +val to_public : t -> public (** Parse the given [string] into an available network option. *) val parse : string -> t option diff --git a/tezt/tests/cloud/scenarios_cli.ml b/tezt/tests/cloud/scenarios_cli.ml index 3fb6e8de615a..4c1c07d1edba 100644 --- a/tezt/tests/cloud/scenarios_cli.ml +++ b/tezt/tests/cloud/scenarios_cli.ml @@ -20,34 +20,6 @@ module Clap = struct let list_of_int ?dummy name = list ~name ?dummy int_of_string string_of_int end -(* [network_simulation_configuration] allows to configure the simulation of a - network, relying on the actual distribution of rights that will be found in - the imported data (data-dir or snapshot). It requires yes crypto to be - enabled. - The simulate option has three modes: - - scatter(x,y): selects the [x] biggest bakers found, and scatters their - baking rights, in a round robin fashion, on [y] baker daemons. This is - particularly useful to scatter the baking power across several baker - daemons, - - map(x,y,z): maps [y] keys from the biggest bakers found onto [y] baker - daemons (theses daemons are handling a single key) and scatters the - remaining [x-y] keys to [z] baker daemons. This is particularly useful to - simulate the behaviour of an actual network, - - disabled: no simulation, we rely on the configuration.stake parameter. - For example: - - scatter(10,2): [[0;2;4;6;8];[1;3;5;7;9]] - - map(10,3,0):[[0];[1];[2;3;4;5;6;7;8;9]] - - map(10,3,2):[[0];[1];[2;5;6;8];[3;5;8;9]]*) -type network_simulation_config = - | Scatter of int * int - | Map of int * int * int - | Disabled - -let simulate_network_to_string = function - | Scatter (x, y) -> Format.sprintf "scatter(%d,%d)" x y - | Map (x, y, z) -> Format.sprintf "map(%d,%d,%d)" x y z - | Disabled -> Format.sprintf "disabled" - let parse_network_simulation_config_from_args simulate_network_arg = let is_positive_param p = if p > 0 then p @@ -80,7 +52,7 @@ let parse_network_simulation_config_from_args simulate_network_arg = |> int_of_string |> is_positive_param in let () = is_arg1_sup_eq_arg2 arg1 arg2 in - Some (Scatter (arg1, arg2)) + Some (Scenarios_configuration.Scatter (arg1, arg2)) else if Str.string_match re_map simulate_network_arg 0 then let arg1 = Str.matched_group 2 simulate_network_arg @@ -95,7 +67,7 @@ let parse_network_simulation_config_from_args simulate_network_arg = |> int_of_string |> is_positive_param in let () = is_arg1_sup_eq_arg2 arg1 (arg2 + arg3) in - Some (Map (arg1, arg2, arg3)) + Some (Scenarios_configuration.Map (arg1, arg2, arg3)) else Test.fail "Unexpected network simulation config (--simulation) [%s]" @@ -126,9 +98,10 @@ module type Dal = sig val network : Network.t - val simulate_network_typ : network_simulation_config Clap.typ + val simulate_network_typ : + Scenarios_configuration.network_simulation_config Clap.typ - val simulate_network : network_simulation_config + val simulate_network : Scenarios_configuration.network_simulation_config val snapshot : Snapshot_helpers.t @@ -138,7 +111,7 @@ module type Dal = sig val bakers : string list - val stake_machine_type : string list option + val stake_machine_type : string list val dal_producers_slot_indices : int list @@ -208,26 +181,49 @@ module Dal () : Dal = struct "All the options related to running DAL scenarios onto the cloud" "DAL" + let config_file = + Clap.optional_string + ~section + ~long:"config-file" + ~description:"Configuration file for the tezt_cloud scenario" + () + + let config = + match config_file with + | None -> + Data_encoding.Json.destruct Scenarios_configuration.DAL.encoding (`O []) + | Some file -> + let json = Ezjsonm.from_channel (In_channel.open_text file) in + Format.printf "%s@." (Ezjsonm.value_to_string json) ; + Data_encoding.Json.destruct Scenarios_configuration.DAL.encoding json + let blocks_history = Clap.default_int ~section ~long:"blocks-history" ~description:"Number of blocks history kept in memory. Default value: 100" - 100 + (Option.value ~default:100 config.blocks_history) let fundraiser = - Clap.optional_string - ~section - ~long:"fundraiser" - ~description:"Fundraiser secret key that has enough money on test network" - () + let from_cli = + Clap.optional_string + ~section + ~long:"fundraiser" + ~description: + "Fundraiser secret key that has enough money on test network" + () + in + Option.fold ~none:config.fundraiser ~some:Option.some from_cli let producer_key = - Clap.optional_string - ~section - ~long:"producer-key" - ~description:"Producer secret key that has enough money" - () + let from_cli = + Clap.optional_string + ~section + ~long:"producer-key" + ~description:"Producer secret key that has enough money" + () + in + Option.fold ~none:config.producer_key ~some:Option.some from_cli let producers_delay = Clap.default_int @@ -236,7 +232,14 @@ module Dal () : Dal = struct ~description: "Delay in levels between two slot productions. Default is 1 meaning \ \"produce every level\"." - 1 + (Option.value ~default:1 config.producers_delay) + + let network_typ : Network.t Clap.typ = + Clap.typ + ~name:"network" + ~dummy:`Ghostnet + ~parse:Network.parse + ~show:Network.to_string let network = Clap.default @@ -247,14 +250,15 @@ module Dal () : Dal = struct (sandbox,ghostnet,nextnet-YYYY-MM-DD,weeklynet-YYYY-MM-DD,...)" ~description:"Allow to specify a network to use for the scenario" network_typ - `Sandbox + (Option.value ~default:`Sandbox config.network) - let simulate_network_typ : network_simulation_config Clap.typ = + let simulate_network_typ : + Scenarios_configuration.network_simulation_config Clap.typ = Clap.typ ~name:"simulate_network" - ~dummy:Disabled + ~dummy:Scenarios_configuration.Disabled ~parse:parse_network_simulation_config_from_args - ~show:simulate_network_to_string + ~show:Scenarios_configuration.simulate_network_to_string let simulate_network = Clap.default @@ -281,7 +285,7 @@ module Dal () : Dal = struct - scatter(10,2): [[0;2;4;6;8];[1;3;5;7;9]]\n\ - map(10,3):[[0];[1];[2;3;4;5;6;7;8;9]]" simulate_network_typ - Disabled + (Option.value ~default:Disabled config.simulate_network) let snapshot = Clap.default @@ -291,13 +295,14 @@ module Dal () : Dal = struct "Snapshot file, which is stored locally, to initiate the scenario with \ some data" snapshot_typ - No_snapshot + (Option.value ~default:No_snapshot config.snapshot) let bootstrap = Clap.flag ~section ~set_long:"bootstrap" - (match network with `Sandbox -> true | _ -> false) + (let default = match network with `Sandbox -> true | _ -> false in + Option.value ~default config.bootstrap) let stake_repartition_typ : Network.stake_repartition Clap.typ = let open Network in @@ -331,9 +336,9 @@ module Dal () : Dal = struct ~show:(function | Custom l -> l |> List.map string_of_int |> String.concat (String.make 1 ',') - | Mimic {network; max_nb_bakers = None} -> Network.to_string network + | Mimic {network; max_nb_bakers = None} -> to_string network | Mimic {network; max_nb_bakers = Some n} -> - Format.sprintf "%s_%d" (Network.to_string network) n) + Format.sprintf "%s_%d" (to_string network) n) let stake = Clap.default @@ -347,45 +352,55 @@ module Dal () : Dal = struct provided share repartitions is the same as on this network (truncated \ to the N biggest delegates if _ is given)." stake_repartition_typ - (if network = `Sandbox && simulate_network = Disabled then Custom [100] - else Custom []) + (let default = + if network = `Sandbox && simulate_network = Disabled then + Network.Custom [100] + else Custom [] + in + Option.value ~default config.stake) let bakers = - Clap.list_string - ~section - ~long:"bakers" - ~placeholder:" " - ~description: - "Specify a baker secret key to bake with. While [--stake] is mostly \ - used for private networks, this one can be used on public networks." - () + config.bakers + @ Clap.list_string + ~section + ~long:"bakers" + ~placeholder:" " + ~description: + "Specify a baker secret key to bake with. While [--stake] is mostly \ + used for private networks, this one can be used on public networks." + () let stake_machine_type = let stake_machine_type_typ = Clap.list ~name:"stake_machine_type" ~dummy:["foo"] Fun.id Fun.id in - Clap.optional - ~section - ~long:"stake-machine-type" - ~placeholder:",,, ..." - ~description: - "Specify the machine type used by the stake. The nth machine type will \ - be assigned to the nth stake specified with [--stake]. If less \ - machine types are specified, the default one (or the one specified by \ - --machine-type) will be used." - stake_machine_type_typ - () + let from_cli = + Clap.optional + ~section + ~long:"stake-machine-type" + ~placeholder:",,, ..." + ~description: + "Specify the machine type used by the stake. The nth machine type \ + will be assigned to the nth stake specified with [--stake]. If less \ + machine types are specified, the default one (or the one specified \ + by --machine-type) will be used." + stake_machine_type_typ + () + in + Option.fold ~none:config.stake_machine_type ~some:Fun.id from_cli let dal_producers_slot_indices = - Clap.default - ~section - ~long:"producer-slot-indices" - ~description: - "Specify the slot indices for DAL producers to run. The number of DAL \ - producers run is the size of the list unless `--producers` is also \ - specified, in that case it takes precedence over this argument." - (Clap.list_of_int "producer_slot_indices") - [] + config.dal_producers_slot_indices + @ Clap.default + ~section + ~long:"producer-slot-indices" + ~description: + "Specify the slot indices for DAL producers to run. The number of \ + DAL producers run is the size of the list unless `--producers` is \ + also specified, in that case it takes precedence over this \ + argument." + (Clap.list_of_int "producer_slot_indices") + [] let producers = Clap.default_int @@ -399,35 +414,42 @@ module Dal () : Dal = struct continue incrementing from the last specified index. For example, to \ start 5 producers from index 5, use `--producers 5 \ --producer-slot-indices 5`." - (List.length dal_producers_slot_indices) + (Option.value + ~default:(List.length dal_producers_slot_indices) + config.producers) let producer_machine_type = - Clap.optional_string - ~section - ~long:"producer-machine-type" - ~description:"Machine type used for the DAL producers" - () + let from_cli = + Clap.optional_string + ~section + ~long:"producer-machine-type" + ~description:"Machine type used for the DAL producers" + () + in + Option.fold ~none:config.producer_machine_type ~some:Option.some from_cli let observer_slot_indices = - Clap.default - ~section - ~long:"observer-slot-indices" - ~placeholder:",,, ..." - ~description: - "For each slot index specified, an observer will be created to observe \ - this slot index." - (Clap.list_of_int "observer_slot_indices") - [] + config.observer_slot_indices + @ Clap.default + ~section + ~long:"observer-slot-indices" + ~placeholder:",,, ..." + ~description: + "For each slot index specified, an observer will be created to \ + observe this slot index." + (Clap.list_of_int "observer_slot_indices") + [] let observer_pkhs = - Clap.list_string - ~section - ~long:"observer-pkh" - ~placeholder:"" - ~description: - "Enable to run a DAL node following the same topics as the baker pkh \ - given in input" - () + config.observer_pkhs + @ Clap.list_string + ~section + ~long:"observer-pkh" + ~placeholder:"" + ~description: + "Enable to run a DAL node following the same topics as the baker pkh \ + given in input" + () let protocol = let protocol_typ = @@ -448,10 +470,17 @@ module Dal () : Dal = struct ~placeholder:" (such as alpha, oxford,...)" ~description:"Specify the economic protocol used for this test" protocol_typ - (Network.default_protocol network) + (Option.value ~default:(Network.default_protocol network) config.protocol) let data_dir = - Clap.optional_string ~section ~long:"data-dir" ~placeholder:"" () + let from_cli = + Clap.optional_string + ~section + ~long:"data-dir" + ~placeholder:"" + () + in + Option.fold ~none:config.data_dir ~some:Option.some from_cli let tezlink = Clap.flag @@ -459,26 +488,37 @@ module Dal () : Dal = struct ~set_long:"tezlink" ~unset_long:"no-tezlink" ~description:"Run Tezlink" - false + (Option.value ~default:false config.tezlink) let etherlink = Clap.flag ~section ~set_long:"etherlink" (* If --tezlink is given, there is no need to also pass --etherlink *) - tezlink + (Option.value ~default:tezlink config.etherlink) let etherlink_sequencer = (* We want the sequencer to be active by default if etherlink is activated. *) - Clap.flag ~section ~unset_long:"no-etherlink-sequencer" etherlink + Clap.flag + ~section + ~unset_long:"no-etherlink-sequencer" + (Option.value ~default:etherlink config.etherlink_sequencer) let etherlink_producers = - Clap.default_int ~section ~long:"etherlink-producers" 0 + Clap.default_int + ~section + ~long:"etherlink-producers" + (Option.value ~default:0 config.etherlink_producers) let etherlink_chain_id = - Clap.optional_int ~section ~long:"etherlink-chain-id" () + let from_cli = Clap.optional_int ~section ~long:"etherlink-chain-id" () in + Option.fold ~none:config.etherlink_chain_id ~some:Option.some from_cli - let echo_rollup = Clap.flag ~section ~set_long:"echo-rollup" false + let echo_rollup = + Clap.flag + ~section + ~set_long:"echo-rollup" + (Option.value ~default:false config.echo_rollup) let disconnect = let disconnect_typ = @@ -493,19 +533,23 @@ module Dal () : Dal = struct let show (d, r) = Format.sprintf "%d,%d" d r in Clap.typ ~name:"disconnect" ~dummy:(10, 10) ~parse ~show in - Clap.optional - ~section - ~long:"disconnect" - ~placeholder:"," - ~description: - "If this argument is provided, bakers will disconnect in turn each \ - levels, and each will reconnect after a delay \ - of levels." - disconnect_typ - () + let from_cli = + Clap.optional + ~section + ~long:"disconnect" + ~placeholder:"," + ~description: + "If this argument is provided, bakers will disconnect in turn each \ + levels, and each will reconnect after a \ + delay of levels." + disconnect_typ + () + in + Option.fold ~none:config.disconnect ~some:Option.some from_cli let etherlink_dal_slots = - Clap.list_int ~section ~long:"etherlink-dal-slots" () + config.etherlink_dal_slots + @ Clap.list_int ~section ~long:"etherlink-dal-slots" () let teztale = Clap.flag @@ -513,41 +557,56 @@ module Dal () : Dal = struct ~set_long:"teztale" ~unset_long:"no-teztale" ~description:"Runs teztale" - false + (Option.value ~default:false config.teztale) let octez_release = - Clap.optional_string - ~section - ~long:"octez-release" - ~placeholder:"" - ~description: - "Use the octez release instead of local octez binaries." - () + let from_cli = + Clap.optional_string + ~section + ~long:"octez-release" + ~placeholder:"" + ~description: + "Use the octez release instead of local octez binaries." + () + in + Option.fold ~none:config.octez_release ~some:Option.some from_cli let memtrace = Clap.flag ~section ~set_long:"memtrace" ~description:"Use memtrace on all the services" - false + (Option.value ~default:false config.memtrace) let bootstrap_node_identity_file = - Clap.optional_string - ~section - ~long:"bootstrap-node-identity" - ~description: - "The bootstrap node identity file. Warning: this argument may be \ - removed in a future release." - () + let from_cli = + Clap.optional_string + ~section + ~long:"bootstrap-node-identity" + ~description: + "The bootstrap node identity file. Warning: this argument may be \ + removed in a future release." + () + in + Option.fold + ~none:config.bootstrap_node_identity_file + ~some:Option.some + from_cli let bootstrap_dal_node_identity_file = - Clap.optional_string - ~section - ~long:"bootstrap-dal-node-identity" - ~description: - "The bootstrap DAL node identity file. Warning: this argument may be \ - removed in a future release." - () + let from_cli = + Clap.optional_string + ~section + ~long:"bootstrap-dal-node-identity" + ~description: + "The bootstrap DAL node identity file. Warning: this argument may be \ + removed in a future release." + () + in + Option.fold + ~none:config.bootstrap_dal_node_identity_file + ~some:Option.some + from_cli let refresh_binaries = Clap.flag @@ -561,7 +620,7 @@ module Dal () : Dal = struct Furthermore, it is not the recommended way to do so, but this option \ also allows to use a docker image without binaries (like the provided \ debian one) and to copy the local binaries to the proxy." - false + (Option.value ~default:false config.refresh_binaries) let node_external_rpc_server = Clap.flag @@ -569,7 +628,7 @@ module Dal () : Dal = struct ~set_long:"node-external-rpc-server" ~unset_long:"no-node-external-rpc-server" ~description:"Use the external RPC server on the L1 nodes" - false + (Option.value ~default:false config.node_external_rpc_server) let with_dal = Clap.flag @@ -580,7 +639,7 @@ module Dal () : Dal = struct "No bootstrap DAL node is run and bakers do not run a DAL node \ (default is 'false'). DAL nodes can be activated via other options \ such as [--producers]." - true + (Option.value ~default:true config.with_dal) let proxy_localhost = Clap.flag @@ -591,24 +650,25 @@ module Dal () : Dal = struct "All agents run on the proxy VM if the proxy mode is activated. This \ can be used to solve a bug with the Tezt Cloud library. This option \ will be removed once the bug is fixed" - false + (Option.value ~default:false config.proxy_localhost) let disable_shard_validation = Clap.flag ~section ~set_long:"disable-shard-validation" ~description:"All DAL nodes will bypass the shard validation stage." - false + (Option.value ~default:false config.disable_shard_validation) let ignore_pkhs = - Clap.list_string - ~section - ~long:"ignore-pkhs" - ~placeholder:" " - ~description: - "Specify a list of public key hashes for which all the producers will \ - not publish the associated shards." - () + config.ignore_pkhs + @ Clap.list_string + ~section + ~long:"ignore-pkhs" + ~placeholder:" " + ~description: + "Specify a list of public key hashes for which all the producers \ + will not publish the associated shards." + () let ppx_profiling = Clap.flag @@ -617,17 +677,18 @@ module Dal () : Dal = struct ~description: "Enable PPX profiling on all components. The level of verbosity is by \ default `Debug` and the format of the output is `txt`. " - false + (Option.value ~default:false config.ppx_profiling) let ppx_profiling_backends = - Clap.list_string - ~section - ~long:"ppx-profiling-backends" - ~description: - "Select the backends used by the profiler, bypassing the defaults \ - selection: always `txt` and `json`, and also `prometheus` if \ - `--prometheus` and `opentelemetry` if `--opentelemetry`." - () + config.ppx_profiling_backends + @ Clap.list_string + ~section + ~long:"ppx-profiling-backends" + ~description: + "Select the backends used by the profiler, bypassing the defaults \ + selection: always `txt` and `json`, and also `prometheus` if \ + `--prometheus` and `opentelemetry` if `--opentelemetry`." + () let enable_network_health_monitoring = Clap.flag @@ -637,7 +698,7 @@ module Dal () : Dal = struct ~description: "If specified, the network health monitoring app.\n\ Recommendation: enable only for public dal bootstrap node deployments" - false + (Option.value ~default:false config.enable_network_health_monitoring) end module type Layer1 = sig diff --git a/tezt/tests/cloud/scenarios_configuration.ml b/tezt/tests/cloud/scenarios_configuration.ml new file mode 100644 index 000000000000..3da21bfdc0d6 --- /dev/null +++ b/tezt/tests/cloud/scenarios_configuration.ml @@ -0,0 +1,306 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2025 Nomadic Labs *) +(* *) +(*****************************************************************************) + +type network_simulation_config = + | Scatter of int * int + | Map of int * int * int + | Disabled + +let network_simulation_config_encoding = + let open Data_encoding in + union + [ + case + (Tag 1) + ~title:"scatter" + (tup2 int31 int31) + (function + | Scatter (nb_keys, nb_daemons) -> Some (nb_keys, nb_daemons) + | _ -> None) + (fun (nb_keys, nb_daemons) -> Scatter (nb_keys, nb_daemons)); + case + (Tag 2) + ~title:"map" + (tup3 int31 int31 int31) + (function + | Map (nb_keys, nb_alone_bakers, nb_additional_daemons) -> + Some (nb_keys, nb_alone_bakers, nb_additional_daemons) + | _ -> None) + (fun (nb_keys, nb_alone_bakers, nb_additional_daemons) -> + Map (nb_keys, nb_alone_bakers, nb_additional_daemons)); + case + (Tag 3) + ~title:"disabled" + empty + (function Disabled -> Some () | _ -> None) + (fun () -> Disabled); + ] + +let simulate_network_to_string = function + | Scatter (x, y) -> Format.sprintf "scatter(%d,%d)" x y + | Map (x, y, z) -> Format.sprintf "map(%d,%d,%d)" x y z + | Disabled -> Format.sprintf "disabled" + +module DAL = struct + type t = { + blocks_history : int option; + producer_key : string option; + fundraiser : string option; + network : Network.t option; + simulate_network : network_simulation_config option; + snapshot : Snapshot_helpers.t option; + bootstrap : bool option; + stake : Network.stake_repartition option; + bakers : string list; + stake_machine_type : string list; + dal_producers_slot_indices : int list; + producers : int option; + producers_delay : int option; + producer_machine_type : string option; + observer_slot_indices : int list; + observer_pkhs : string list; + protocol : Protocol.t option; + data_dir : string option; + etherlink : bool option; + etherlink_sequencer : bool option; + etherlink_producers : int option; + etherlink_chain_id : int option; + echo_rollup : bool option; + disconnect : (int * int) option; + etherlink_dal_slots : int list; + teztale : bool option; + octez_release : string option; + memtrace : bool option; + bootstrap_node_identity_file : string option; + bootstrap_dal_node_identity_file : string option; + refresh_binaries : bool option; + node_external_rpc_server : bool option; + with_dal : bool option; + proxy_localhost : bool option; + disable_shard_validation : bool option; + ignore_pkhs : string list; + ppx_profiling : bool option; + ppx_profiling_backends : string list; + enable_network_health_monitoring : bool option; + tezlink : bool option; + } + + let encoding = + let open Data_encoding in + conv + (fun { + blocks_history; + producer_key; + fundraiser; + network; + simulate_network; + snapshot; + bootstrap; + stake; + bakers; + stake_machine_type; + dal_producers_slot_indices; + producers; + producers_delay; + producer_machine_type; + observer_slot_indices; + observer_pkhs; + protocol; + data_dir; + etherlink; + etherlink_sequencer; + etherlink_producers; + etherlink_chain_id; + echo_rollup; + disconnect; + etherlink_dal_slots; + teztale; + octez_release; + memtrace; + bootstrap_node_identity_file; + bootstrap_dal_node_identity_file; + refresh_binaries; + node_external_rpc_server; + with_dal; + proxy_localhost; + disable_shard_validation; + ignore_pkhs; + ppx_profiling; + ppx_profiling_backends; + enable_network_health_monitoring; + tezlink; + } -> + ( ( ( blocks_history, + producer_key, + fundraiser, + network, + simulate_network, + snapshot, + bootstrap, + stake, + bakers, + stake_machine_type ), + ( dal_producers_slot_indices, + producers, + producers_delay, + producer_machine_type, + observer_slot_indices, + observer_pkhs, + protocol, + data_dir, + etherlink, + etherlink_sequencer ) ), + ( ( etherlink_producers, + etherlink_chain_id, + echo_rollup, + disconnect, + etherlink_dal_slots, + teztale, + octez_release, + memtrace, + bootstrap_node_identity_file, + bootstrap_dal_node_identity_file ), + ( refresh_binaries, + node_external_rpc_server, + with_dal, + proxy_localhost, + disable_shard_validation, + ignore_pkhs, + ppx_profiling, + ppx_profiling_backends, + enable_network_health_monitoring, + tezlink ) ) )) + (fun ( ( ( blocks_history, + producer_key, + fundraiser, + network, + simulate_network, + snapshot, + bootstrap, + stake, + bakers, + stake_machine_type ), + ( dal_producers_slot_indices, + producers, + producers_delay, + producer_machine_type, + observer_slot_indices, + observer_pkhs, + protocol, + data_dir, + etherlink, + etherlink_sequencer ) ), + ( ( etherlink_producers, + etherlink_chain_id, + echo_rollup, + disconnect, + etherlink_dal_slots, + teztale, + octez_release, + memtrace, + bootstrap_node_identity_file, + bootstrap_dal_node_identity_file ), + ( refresh_binaries, + node_external_rpc_server, + with_dal, + proxy_localhost, + disable_shard_validation, + ignore_pkhs, + ppx_profiling, + ppx_profiling_backends, + enable_network_health_monitoring, + tezlink ) ) ) -> + { + blocks_history; + producer_key; + fundraiser; + network; + simulate_network; + snapshot; + bootstrap; + stake; + bakers; + stake_machine_type; + dal_producers_slot_indices; + producers; + producers_delay; + producer_machine_type; + observer_slot_indices; + observer_pkhs; + protocol; + data_dir; + etherlink; + etherlink_sequencer; + etherlink_producers; + etherlink_chain_id; + echo_rollup; + disconnect; + etherlink_dal_slots; + teztale; + octez_release; + memtrace; + bootstrap_node_identity_file; + bootstrap_dal_node_identity_file; + refresh_binaries; + node_external_rpc_server; + with_dal; + proxy_localhost; + disable_shard_validation; + ignore_pkhs; + ppx_profiling; + ppx_profiling_backends; + enable_network_health_monitoring; + tezlink; + }) + (merge_objs + (merge_objs + (obj10 + (opt "blocks_history" int31) + (opt "producer_key" string) + (opt "fundraiser" string) + (opt "network" Network.encoding) + (opt "simulate_network" network_simulation_config_encoding) + (opt "snapshot" Snapshot_helpers.encoding) + (opt "bootstrap" bool) + (opt "stake" Network.stake_repartition_encoding) + (dft "bakers" (list string) []) + (dft "stake_machine_type" (list string) [])) + (obj10 + (dft "dal_producers_slot_indices" (list int31) []) + (opt "producers" int31) + (opt "producers_delay" int31) + (opt "producer_machine_type" string) + (dft "observer_slot_indices" (list int31) []) + (dft "observer_pkhs" (list string) []) + (opt "protocol" Protocol.encoding) + (opt "data_dir" string) + (opt "etherlink" bool) + (opt "etherlink_sequencer" bool))) + (merge_objs + (obj10 + (opt "etherlink_producers" int31) + (opt "etherlink_chain_id" int31) + (opt "echo_rollup" bool) + (opt "disconnect" (tup2 int31 int31)) + (dft "etherlink_dal_slots" (list int31) []) + (opt "teztale" bool) + (opt "octez_release" string) + (opt "memtrace" bool) + (opt "bootstrap_node_identity_file" string) + (opt "bootstrap_dal_node_identity_file" string)) + (obj10 + (opt "refresh_binaries" bool) + (opt "node_external_rpc_server" bool) + (opt "with_dal" bool) + (opt "proxy_localhost" bool) + (opt "disable_shard_validation" bool) + (dft "ignore_pkhs" (list string) []) + (opt "ppx_profiling" bool) + (dft "ppx_profiling_backends" (list string) []) + (opt "enable_network_health_monitoring" bool) + (opt "tezlink" bool)))) +end diff --git a/tezt/tests/cloud/scenarios_configuration.mli b/tezt/tests/cloud/scenarios_configuration.mli new file mode 100644 index 000000000000..6dc8ab91098f --- /dev/null +++ b/tezt/tests/cloud/scenarios_configuration.mli @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2025 Nomadic Labs *) +(* *) +(*****************************************************************************) + +(** [network_simulation_configuration] allows to configure the simulation of a + network, relying on the actual distribution of rights that will be found in + the imported data (data-dir or snapshot). It requires yes crypto to be + enabled. + The simulate option has three modes: + - scatter(x,y): selects the [x] biggest bakers found, and scatters their + baking rights, in a round robin fashion, on [y] baker daemons. This is + particularly useful to scatter the baking power across several baker + daemons, + - map(x,y,z): maps [y] keys from the biggest bakers found onto [y] baker + daemons (theses daemons are handling a single key) and scatters the + remaining [x-y] keys to [z] baker daemons. This is particularly useful to + simulate the behaviour of an actual network, + - disabled: no simulation, we rely on the configuration.stake parameter. + For example: + - scatter(10,2): [[0;2;4;6;8];[1;3;5;7;9]] + - map(10,2,1):[[0];[1];[2;3;4;5;6;7;8;9]] + - map(10,2,2):[[0];[1];[2;5;6;8];[3;5;8;9]] *) + +type network_simulation_config = + | Scatter of int * int + | Map of int * int * int + | Disabled + +val network_simulation_config_encoding : + network_simulation_config Data_encoding.t + +val simulate_network_to_string : network_simulation_config -> string + +module DAL : sig + type t = { + blocks_history : int option; + producer_key : string option; + fundraiser : string option; + network : Network.t option; + simulate_network : network_simulation_config option; + snapshot : Snapshot_helpers.t option; + bootstrap : bool option; + stake : Network.stake_repartition option; + bakers : string list; + stake_machine_type : string list; + dal_producers_slot_indices : int list; + producers : int option; + producers_delay : int option; + producer_machine_type : string option; + observer_slot_indices : int list; + observer_pkhs : string list; + protocol : Protocol.t option; + data_dir : string option; + etherlink : bool option; + etherlink_sequencer : bool option; + etherlink_producers : int option; + etherlink_chain_id : int option; + echo_rollup : bool option; + disconnect : (int * int) option; + etherlink_dal_slots : int list; + teztale : bool option; + octez_release : string option; + memtrace : bool option; + bootstrap_node_identity_file : string option; + bootstrap_dal_node_identity_file : string option; + refresh_binaries : bool option; + node_external_rpc_server : bool option; + with_dal : bool option; + proxy_localhost : bool option; + disable_shard_validation : bool option; + ignore_pkhs : string list; + ppx_profiling : bool option; + ppx_profiling_backends : string list; + enable_network_health_monitoring : bool option; + tezlink : bool option; + } + + val encoding : t Data_encoding.t +end diff --git a/tezt/tests/cloud/yes_crypto.ml b/tezt/tests/cloud/yes_crypto.ml index 000015d56a6e..a12b1999f93a 100644 --- a/tezt/tests/cloud/yes_crypto.ml +++ b/tezt/tests/cloud/yes_crypto.ml @@ -6,7 +6,7 @@ (* *) (*****************************************************************************) -open Scenarios_cli +open Scenarios_configuration let yes_crypto_env = String_map.singleton Tezos_crypto.Helpers.yes_crypto_environment_variable "y" diff --git a/tezt/tests/cloud/yes_crypto.mli b/tezt/tests/cloud/yes_crypto.mli index 86cac33b28e8..d20798d390f5 100644 --- a/tezt/tests/cloud/yes_crypto.mli +++ b/tezt/tests/cloud/yes_crypto.mli @@ -10,7 +10,7 @@ which bypasses certain cryptographic confirmations in Octez nodes. *) -open Scenarios_cli +open Scenarios_configuration (** [should_enable_yes_crypto config] returns a flag indicating whether "yes-crypto" mode should be enabled (for [Scatter] and [Map]) -- GitLab From a192cd45a84b60f9f666e00f985246433791df97 Mon Sep 17 00:00:00 2001 From: Guillaume Genestier Date: Fri, 25 Jul 2025 14:43:28 +0200 Subject: [PATCH 2/4] Tezt/Cloud: Add a global tezt-cloud scenario, with a scenario_specific object --- tezt/lib_cloud/cli.ml | 552 ++++++++++++++++++++++++------ tezt/lib_cloud/cli.mli | 2 + tezt/lib_cloud/tezt_cloud.ml | 2 + tezt/lib_cloud/tezt_cloud.mli | 2 + tezt/tests/cloud/scenarios_cli.ml | 17 +- 5 files changed, 449 insertions(+), 126 deletions(-) diff --git a/tezt/lib_cloud/cli.ml b/tezt/lib_cloud/cli.ml index 897809394a6b..2edf906e234c 100644 --- a/tezt/lib_cloud/cli.ml +++ b/tezt/lib_cloud/cli.ml @@ -9,25 +9,317 @@ open Tezt include Cli include Types +type config = { + localhost : bool option; + ssh_host : string option; + monitoring : bool option; + destroy : bool option; + keep_alive : bool option; + project_id : string option; + vms : int option; + vm_base_port : int option; + ports_per_vm : int option; + proxy : bool option; + os : Os.t option; + grafana : bool option; + grafana_legacy_source : bool option; + alert_handlers : string list; + prometheus : bool option; + prometheus_export : bool option; + prometheus_port : int option; + prometheus_export_path : string option; + prometheus_snapshots : (string * int option) list; + prometheus_scrape_interval : int option; + process_monitoring : bool option; + website : bool option; + machine_type : string option; + dockerfile_alias : string option; + website_port : int option; + max_run_duration : int option; + no_max_run_duration : bool option; + tezt_cloud : string option; + dns_domains : string list; + no_dns : bool option; + open_telemetry : bool option; + macosx : bool option; + check_file_consistency : bool option; + docker_host_network : bool option; + push_docker : bool option; + auto_approve : bool option; + faketime : string option; + binaries_path : string option; + log_rotation : int option; + slack_channel_id : string option; + slack_bot_token : string option; + scenario_specific : Data_encoding.Json.t option; +} + +let encoding = + let open Data_encoding in + conv + (fun { + localhost; + ssh_host; + monitoring; + destroy; + keep_alive; + project_id; + vms; + vm_base_port; + ports_per_vm; + proxy; + os; + grafana; + grafana_legacy_source; + alert_handlers; + prometheus; + prometheus_export; + prometheus_port; + prometheus_export_path; + prometheus_snapshots; + prometheus_scrape_interval; + process_monitoring; + website; + machine_type; + dockerfile_alias; + website_port; + max_run_duration; + no_max_run_duration; + tezt_cloud; + dns_domains; + no_dns; + open_telemetry; + macosx; + check_file_consistency; + docker_host_network; + push_docker; + auto_approve; + faketime; + binaries_path; + log_rotation; + slack_channel_id; + slack_bot_token; + scenario_specific; + } -> + ( ( ( localhost, + ssh_host, + monitoring, + destroy, + keep_alive, + project_id, + vms, + vm_base_port, + ports_per_vm, + proxy ), + ( os, + grafana, + grafana_legacy_source, + alert_handlers, + prometheus, + prometheus_export, + prometheus_port, + prometheus_export_path, + prometheus_snapshots, + prometheus_scrape_interval ) ), + ( ( ( process_monitoring, + website, + machine_type, + dockerfile_alias, + website_port, + max_run_duration, + no_max_run_duration, + tezt_cloud, + dns_domains, + no_dns ), + ( open_telemetry, + macosx, + check_file_consistency, + docker_host_network, + push_docker, + auto_approve, + faketime, + binaries_path, + log_rotation, + slack_channel_id ) ), + (slack_bot_token, scenario_specific) ) )) + (fun ( ( ( localhost, + ssh_host, + monitoring, + destroy, + keep_alive, + project_id, + vms, + vm_base_port, + ports_per_vm, + proxy ), + ( os, + grafana, + grafana_legacy_source, + alert_handlers, + prometheus, + prometheus_export, + prometheus_port, + prometheus_export_path, + prometheus_snapshots, + prometheus_scrape_interval ) ), + ( ( ( process_monitoring, + website, + machine_type, + dockerfile_alias, + website_port, + max_run_duration, + no_max_run_duration, + tezt_cloud, + dns_domains, + no_dns ), + ( open_telemetry, + macosx, + check_file_consistency, + docker_host_network, + push_docker, + auto_approve, + faketime, + binaries_path, + log_rotation, + slack_channel_id ) ), + (slack_bot_token, scenario_specific) ) ) -> + { + localhost; + ssh_host; + monitoring; + destroy; + keep_alive; + project_id; + vms; + vm_base_port; + ports_per_vm; + proxy; + os; + grafana; + grafana_legacy_source; + alert_handlers; + prometheus; + prometheus_export; + prometheus_port; + prometheus_export_path; + prometheus_snapshots; + prometheus_scrape_interval; + process_monitoring; + website; + machine_type; + dockerfile_alias; + website_port; + max_run_duration; + no_max_run_duration; + tezt_cloud; + dns_domains; + no_dns; + open_telemetry; + macosx; + check_file_consistency; + docker_host_network; + push_docker; + auto_approve; + faketime; + binaries_path; + log_rotation; + slack_channel_id; + slack_bot_token; + scenario_specific; + }) + (merge_objs + (merge_objs + (obj10 + (opt "localhost" bool) + (opt "ssh_host" string) + (opt "monitoring" bool) + (opt "destroy" bool) + (opt "keep_alive" bool) + (opt "project_id" string) + (opt "vms" int31) + (opt "vm_base_port" int31) + (opt "ports_per_vm" int31) + (opt "proxy" bool)) + (obj10 + (opt "os" Os.encoding) + (opt "grafana" bool) + (opt "grafana_legacy_source" bool) + (dft "alert_handlers" (list string) []) + (opt "prometheus" bool) + (opt "prometheus_export" bool) + (opt "prometheus_port" int31) + (opt "prometheus_export_path" string) + (dft "prometheus_snapshots" (list (tup2 string (option int31))) []) + (opt "prometheus_scrape_interval" int31))) + (merge_objs + (merge_objs + (obj10 + (opt "process_monitoring" bool) + (opt "website" bool) + (opt "machine_type" string) + (opt "dockerfile_alias" string) + (opt "website_port" int31) + (opt "max_run_duration" int31) + (opt "no_max_run_duration" bool) + (opt "tezt_cloud" string) + (dft "dns_domains" (list string) []) + (opt "no_dns" bool)) + (obj10 + (opt "open_telemetry" bool) + (opt "macosx" bool) + (opt "check_file_consistency" bool) + (opt "docker_host_network" bool) + (opt "push_docker" bool) + (opt "auto_approve" bool) + (opt "faketime" string) + (opt "binaries_path" string) + (opt "log_rotation" int31) + (opt "slack_channel_id" string))) + (obj2 + (opt "slack_bot_token" string) + (opt "scenario_specific" Data_encoding.Json.encoding)))) + let section = Clap.section ~description:"All the options related to Tezt cloud library" "Cloud" +let config_file = + Clap.optional_string + ~section + ~long:"config-file" + ~description:"Configuration file for the tezt_cloud scenario" + () + +let config = + match config_file with + | None -> Data_encoding.Json.destruct encoding (`O []) + | Some file -> + let json = Ezjsonm.from_channel (In_channel.open_text file) in + Format.printf "%s@." (Ezjsonm.value_to_string json) ; + Data_encoding.Json.destruct encoding json + +let scenario_specific = Option.value ~default:(`O []) config.scenario_specific + +let some = Option.some + let localhost = Clap.flag ~section ~set_long:"localhost" ~unset_long:"cloud" ~description:"If set, the test is run locally" - false + (Option.value ~default:false config.localhost) let ssh_host = - Clap.optional_string - ~section - ~long:"ssh-host" - ~description:"Whether to provision a non-gcp vm host via ssh" - () + let from_cli = + Clap.optional_string + ~section + ~long:"ssh-host" + ~description:"Whether to provision a non-gcp vm host via ssh" + () + in + Option.fold ~none:config.ssh_host ~some from_cli let ssh_private_key = Clap.optional_string @@ -44,7 +336,7 @@ let monitoring = ~description: "If set, all the VMs are monitored with netdata. The monitoring \ dashboard is accessible on port 13999 of the monitored VM." - false + (Option.value ~default:false config.monitoring) let destroy = Clap.flag @@ -52,7 +344,7 @@ let destroy = ~set_long:"destroy" ~unset_long:"no-destroy" ~description:"If set, the machines are destroyed at the end of the test" - false + (Option.value ~default:false config.destroy) let keep_alive = Clap.flag @@ -61,37 +353,43 @@ let keep_alive = ~description: "If set, the test will prompt the user to press to end the test. \ This option can be used to inspect VMs state at the end of a scenrio." - false + (Option.value ~default:false config.keep_alive) let project_id = - Clap.optional_string - ~section - ~long:"project-id" - ~description: - "Allows to specify a given project id. Otherwise, a default one will be \ - fetched with `gcloud config get-value project`" - () + let from_cli = + Clap.optional_string + ~section + ~long:"project-id" + ~description: + "Allows to specify a given project id. Otherwise, a default one will \ + be fetched with `gcloud config get-value project`" + () + in + Option.fold ~none:config.project_id ~some from_cli let vms = - Clap.optional_int - ~section - ~long:"vms-limit" - ~description:"Maximum number of VMs running during the test." - () + let from_cli = + Clap.optional_int + ~section + ~long:"vms-limit" + ~description:"Maximum number of VMs running during the test." + () + in + Option.fold ~none:config.vms ~some from_cli let vm_base_port = Clap.default_int ~section ~long:"vm-base-port" ~description:"The first available port on the VM" - 30_000 + (Option.value ~default:30_000 config.vm_base_port) let ports_per_vm = Clap.default_int ~section ~long:"ports-per-vm" ~description:"Number of opened ports per VM (default is 50)" - 50 + (Option.value ~default:50 config.ports_per_vm) let proxy = Clap.flag @@ -99,7 +397,7 @@ let proxy = ~set_long:"proxy" ~description: "Enables to run the orchestrator on a VM instead of the host machine" - false + (Option.value ~default:false config.proxy) let os = Clap.default @@ -109,7 +407,7 @@ let os = ~description: "The OS to be used for the VM (default is cos). Other possible value is \ 'debian'." - Os.Cos + (Option.value ~default:Os.Cos config.os) let grafana = Clap.flag @@ -117,7 +415,9 @@ let grafana = ~set_long:"grafana" ~unset_long:"no-grafana" ~description:"Flag to set whether to run grafana" - (((not localhost) || proxy) && os = Os.Cos) + (Option.value + ~default:(((not localhost) || proxy) && os = Os.Cos) + config.grafana) let grafana_legacy_source = Clap.flag @@ -127,14 +427,15 @@ let grafana_legacy_source = "Flag to indicate to use grafana legacy 'Prometheus' source name when \ importing a prometheus snapshot. Newer dashboards should use \ ${datasource} as source instead of the hardcoded 'Prometheus' name." - false + (Option.value ~default:false config.grafana_legacy_source) let alert_handlers = - Clap.list_string - ~section - ~long:"alert-handler" - ~description:"Specify an alert handler to be registered by alert manager." - () + config.alert_handlers + @ Clap.list_string + ~section + ~long:"alert-handler" + ~description:"Specify an alert handler to be registered by alert manager." + () let prometheus = Clap.flag @@ -142,7 +443,7 @@ let prometheus = ~set_long:"prometheus" ~unset_long:"no-prometheus" ~description:"Flag to set whether metrics are exported into prometheus" - (grafana || alert_handlers <> []) + (Option.value ~default:(grafana || alert_handlers <> []) config.prometheus) let prometheus_export = Clap.flag @@ -150,7 +451,7 @@ let prometheus_export = ~set_long:"prometheus-export" ~unset_long:"no-prometheus-export" ~description:"Export a Prometheus snapshot at the end of the scenario" - true + (Option.value ~default:true config.prometheus_export) let default_prometheus_port = 9090 @@ -162,14 +463,17 @@ let prometheus_port = (sf "Set the port on which the prometheus instance will run (default: %d)." default_prometheus_port) - default_prometheus_port + (Option.value ~default:default_prometheus_port config.prometheus_port) let prometheus_export_path = - Clap.optional_string - ~section - ~long:"prometheus-export-path" - ~description:"Path of the prometheus snapshot" - () + let from_cli = + Clap.optional_string + ~section + ~long:"prometheus-export-path" + ~description:"Path of the prometheus snapshot" + () + in + Option.fold ~none:config.prometheus_export_path ~some from_cli let prometheus_snapshots = let parse str = @@ -185,18 +489,19 @@ let prometheus_snapshots = let typ = Clap.typ ~name:"prometheus-snapshot-imported" ~dummy:("", None) ~parse ~show in - Clap.list - typ - ~section - ~long:"prometheus-snapshots" - ~placeholder:"/path/to/snapshot[:port]" - ~description: - (sf - "Path to the snapshot to load in a prometheus docker container. If no \ - port is specified, a port will be automatically assigned starting \ - with the value of --prometheus-port (default: %d)" - default_prometheus_port) - () + config.prometheus_snapshots + @ Clap.list + typ + ~section + ~long:"prometheus-snapshots" + ~placeholder:"/path/to/snapshot[:port]" + ~description: + (sf + "Path to the snapshot to load in a prometheus docker container. If \ + no port is specified, a port will be automatically assigned \ + starting with the value of --prometheus-port (default: %d)" + default_prometheus_port) + () let prometheus_scrape_interval = Clap.default_int @@ -204,7 +509,7 @@ let prometheus_scrape_interval = ~long:"prometheus-scrape-interval" ~description: "Set the scraping interval of the prometheus instance (default: 5)" - 5 + (Option.value ~default:5 config.prometheus_scrape_interval) let process_monitoring = Clap.flag @@ -214,7 +519,8 @@ let process_monitoring = ~description: "Flag to set process monitoring through prometheus process exporter. \ Default is set when prometheus is set" - prometheus (* Automatically enable when enabling prometheus *) + (Option.value ~default:prometheus config.process_monitoring) +(* Automatically enable when enabling prometheus *) let website = Clap.flag @@ -224,7 +530,7 @@ let website = ~description: "A webpage is up on localhost to summarize various information related \ to the experiment" - prometheus + (Option.value ~default:prometheus config.website) let machine_type = Clap.default_string @@ -236,16 +542,21 @@ let machine_type = https://cloud.google.com/compute/docs/general-purpose-machines#n2_series). \ Default is %s." Types.Agent_configuration.default_gcp_machine_type) - Types.Agent_configuration.default_gcp_machine_type + (Option.value + ~default:Types.Agent_configuration.default_gcp_machine_type + config.machine_type) let dockerfile_alias = - Clap.optional_string - ~section - ~long:"dockerfile-alias" - ~description: - "Specify the name of the dockerfile alias to use (default is given by \ - the environment variable `TEZT_CLOUD`)" - () + let from_cli = + Clap.optional_string + ~section + ~long:"dockerfile-alias" + ~description: + "Specify the name of the dockerfile alias to use (default is given by \ + the environment variable `TEZT_CLOUD`)" + () + in + Option.fold ~none:config.dockerfile_alias ~some from_cli let website_port = Clap.default_int @@ -255,7 +566,9 @@ let website_port = (* When the website is run by the orchestrator, it is easier to use port 80. We could decide in the future to use 80 by default. *) - (if proxy && localhost then 80 else 8080) + (Option.value + ~default:(if proxy && localhost then 80 else 8080) + config.website_port) let max_run_duration = Clap.default_int @@ -264,7 +577,7 @@ let max_run_duration = ~description: "Specify the maximum time (in seconds) of a VM (from the first time it \ was created)." - 7200 + (Option.value ~default:7200 config.max_run_duration) let no_max_run_duration = Clap.flag @@ -273,28 +586,32 @@ let no_max_run_duration = ~description:"Ensure the VM can only be destroyed manually." (* If the proxy mode is active, we don't want to use [max_run_duration] since it aims to run long running tests. *) - (proxy || os <> Os.Cos) + (Option.value ~default:(proxy || os <> Os.Cos) config.no_max_run_duration) let tezt_cloud = - Clap.optional_string - ~section - ~long:"tezt-cloud" - ~description:"Overwrite the TEZT_CLOUD variable" - () + let from_cli = + Clap.optional_string + ~section + ~long:"tezt-cloud" + ~description:"Overwrite the TEZT_CLOUD variable" + () + in + Option.fold ~none:config.tezt_cloud ~some from_cli let dns_domains = - Clap.list_string - ~section - ~long:"dns-domain" - ~long_synonyms:["dns"] - ~description: - "Register a list of DNS domains. By default a domain is registered when \ - using the proxy mode. In that case the domain will be prepended by the \ - value of the `tezt-cloud` parameter and suffixed by the domain \ - registered under the zone name `tezt-cloud` (check the README to get \ - more details). The format expects domains that have suffixes matching \ - domains registered with the GCP project." - () + config.dns_domains + @ Clap.list_string + ~section + ~long:"dns-domain" + ~long_synonyms:["dns"] + ~description: + "Register a list of DNS domains. By default a domain is registered \ + when using the proxy mode. In that case the domain will be prepended \ + by the value of the `tezt-cloud` parameter and suffixed by the domain \ + registered under the zone name `tezt-cloud` (check the README to get \ + more details). The format expects domains that have suffixes matching \ + domains registered with the GCP project." + () let no_dns = Clap.flag @@ -304,7 +621,7 @@ let no_dns = ~description: "Prevent from adding any DNS domain associated with the experiment. This \ cancel any effect of [--dns-domain]." - false + (Option.value ~default:false config.no_dns) let open_telemetry = Clap.flag @@ -313,14 +630,14 @@ let open_telemetry = ~unset_long:"no-open-telemetry" ~set_long_synonyms:["otel"] ~description:"Run the Open Telemetry stack" - false + (Option.value ~default:false config.open_telemetry) let macosx = Clap.flag ~section ~set_long:"macosx" ~description:"Use this flag if you run tezt-cloud from Mac OS/X" - false + (Option.value ~default:false config.macosx) let check_file_consistency = Clap.flag @@ -332,7 +649,7 @@ let check_file_consistency = machine to a VM are consistent (i.e., they have the same hash). \ Although a scenario can opt in or opt out, this flag sets the default \ behavior. Its default value is [true] unless [--macosx] is used." - (not macosx) + (Option.value ~default:(not macosx) config.check_file_consistency) let docker_host_network = Clap.flag @@ -344,7 +661,7 @@ let docker_host_network = network or not. This is not available on Mac OS/X. By default [true] \ unless Mac OS/X is set. If not set, a dedicated docker network is \ created." - (not macosx) + (Option.value ~default:(not macosx) config.docker_host_network) let push_docker = Clap.flag @@ -356,7 +673,7 @@ let push_docker = bandwidth or some time during a redeployment that won't add or remove \ VMs that are already running, it is useful to prevent those containers \ to be pushed." - true + (Option.value ~default:true config.push_docker) let auto_approve = Clap.flag @@ -366,19 +683,22 @@ let auto_approve = ~description: "If set to true (default), don't ask confirmation before updating a \ deployment via terraform." - true + (Option.value ~default:true config.auto_approve) let faketime = - Clap.optional_string - ~section - ~long:"faketime" - ~description: - "This argument specifies the value used to set [FAKETIME] environment \ - variable for the Docker images. Use it with a docker image that uses \ - [libfaketime]. For instance, use [--faketime \"-10d\"] if you want to \ - set your experminent 10 days in the past. See [libfaketime] for a \ - complete overview about the [FAKETIME] available formats." - () + let from_cli = + Clap.optional_string + ~section + ~long:"faketime" + ~description: + "This argument specifies the value used to set [FAKETIME] environment \ + variable for the Docker images. Use it with a docker image that uses \ + [libfaketime]. For instance, use [--faketime \"-10d\"] if you want to \ + set your experminent 10 days in the past. See [libfaketime] for a \ + complete overview about the [FAKETIME] available formats." + () + in + Option.fold ~none:config.faketime ~some from_cli let binaries_path = Clap.default_string @@ -387,7 +707,9 @@ let binaries_path = ~description: "Where to find binaries in the docker image by default (default is: \ '/tmp/tezt-runners')" - Types.Agent_configuration.default_gcp_binaries_path + (Option.value + ~default:Types.Agent_configuration.default_gcp_binaries_path + config.binaries_path) let log_rotation = Clap.default_int @@ -397,7 +719,7 @@ let log_rotation = "Maximum number of log rotations before removing older log files. \ Default is 300 if a log-file is specified.\n\ \ Set to 0 to completely disable log-rotation" - 300 + (Option.value ~default:300 config.log_rotation) let section = Clap.section @@ -405,15 +727,21 @@ let section = "Cloud reporting and alerting options" let slack_channel_id = - Clap.optional_string - ~section - ~long:"slack-channel-id" - ~description:"The Slack channel id to send reports and alerts on" - () + let from_cli = + Clap.optional_string + ~section + ~long:"slack-channel-id" + ~description:"The Slack channel id to send reports and alerts on" + () + in + Option.fold ~none:config.slack_channel_id ~some from_cli let slack_bot_token = - Clap.optional_string - ~section - ~long:"slack-bot-token" - ~description:"The Slack bot token used to send reports and alerts" - () + let from_cli = + Clap.optional_string + ~section + ~long:"slack-bot-token" + ~description:"The Slack bot token used to send reports and alerts" + () + in + Option.fold ~none:config.slack_bot_token ~some from_cli diff --git a/tezt/lib_cloud/cli.mli b/tezt/lib_cloud/cli.mli index e9c8cc3bffa9..d1292d628e62 100644 --- a/tezt/lib_cloud/cli.mli +++ b/tezt/lib_cloud/cli.mli @@ -7,6 +7,8 @@ include module type of Tezt.Cli +val scenario_specific : Data_encoding.Json.t + (** When [localhost] is [true], the cloud scenario should be run locally. This can be used to test a scenario before deploying it. *) val localhost : bool diff --git a/tezt/lib_cloud/tezt_cloud.ml b/tezt/lib_cloud/tezt_cloud.ml index bf719e83fe61..b15cdd90a423 100644 --- a/tezt/lib_cloud/tezt_cloud.ml +++ b/tezt/lib_cloud/tezt_cloud.ml @@ -301,4 +301,6 @@ end module Tezt_cloud_cli = struct let prometheus = Cli.prometheus + + let scenario_specific_json = Cli.scenario_specific end diff --git a/tezt/lib_cloud/tezt_cloud.mli b/tezt/lib_cloud/tezt_cloud.mli index 96d694d87142..3dbb16b2fb6f 100644 --- a/tezt/lib_cloud/tezt_cloud.mli +++ b/tezt/lib_cloud/tezt_cloud.mli @@ -255,6 +255,8 @@ end module Tezt_cloud_cli : sig (** Equivalent to [Cli.prometheus] *) val prometheus : bool + + val scenario_specific_json : Data_encoding.Json.t end (** [register ~tags] register a set of jobs that can be used for setting diff --git a/tezt/tests/cloud/scenarios_cli.ml b/tezt/tests/cloud/scenarios_cli.ml index 4c1c07d1edba..f3024903ffbc 100644 --- a/tezt/tests/cloud/scenarios_cli.ml +++ b/tezt/tests/cloud/scenarios_cli.ml @@ -181,21 +181,10 @@ module Dal () : Dal = struct "All the options related to running DAL scenarios onto the cloud" "DAL" - let config_file = - Clap.optional_string - ~section - ~long:"config-file" - ~description:"Configuration file for the tezt_cloud scenario" - () - let config = - match config_file with - | None -> - Data_encoding.Json.destruct Scenarios_configuration.DAL.encoding (`O []) - | Some file -> - let json = Ezjsonm.from_channel (In_channel.open_text file) in - Format.printf "%s@." (Ezjsonm.value_to_string json) ; - Data_encoding.Json.destruct Scenarios_configuration.DAL.encoding json + Data_encoding.Json.destruct + Scenarios_configuration.DAL.encoding + Tezt_cloud_cli.scenario_specific_json let blocks_history = Clap.default_int -- GitLab From f962de3af57b60f9b38dada2f2c1c9f92e2aee4c Mon Sep 17 00:00:00 2001 From: Guillaume Genestier Date: Fri, 25 Jul 2025 14:43:29 +0200 Subject: [PATCH 3/4] Tezt/Cloud: Information when config file reading fails Co-authored-by: Victor Allombert --- tezt/lib_cloud/cli.ml | 11 +++++++++-- tezt/tests/cloud/scenarios_cli.ml | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tezt/lib_cloud/cli.ml b/tezt/lib_cloud/cli.ml index 2edf906e234c..1df128ad1953 100644 --- a/tezt/lib_cloud/cli.ml +++ b/tezt/lib_cloud/cli.ml @@ -294,10 +294,17 @@ let config_file = let config = match config_file with | None -> Data_encoding.Json.destruct encoding (`O []) - | Some file -> + | Some file -> ( let json = Ezjsonm.from_channel (In_channel.open_text file) in Format.printf "%s@." (Ezjsonm.value_to_string json) ; - Data_encoding.Json.destruct encoding json + try Data_encoding.Json.destruct encoding json with + | Json_encoding.Cannot_destruct (_, e) as exn -> + Log.error + "Cannot load config file: %s - %s" + (Printexc.to_string exn) + (Printexc.to_string e) ; + raise exn + | e -> raise e) let scenario_specific = Option.value ~default:(`O []) config.scenario_specific diff --git a/tezt/tests/cloud/scenarios_cli.ml b/tezt/tests/cloud/scenarios_cli.ml index f3024903ffbc..da1960ae8661 100644 --- a/tezt/tests/cloud/scenarios_cli.ml +++ b/tezt/tests/cloud/scenarios_cli.ml @@ -182,9 +182,18 @@ module Dal () : Dal = struct "DAL" let config = - Data_encoding.Json.destruct - Scenarios_configuration.DAL.encoding - Tezt_cloud_cli.scenario_specific_json + try + Data_encoding.Json.destruct + Scenarios_configuration.DAL.encoding + Tezt_cloud_cli.scenario_specific_json + with + | Json_encoding.Cannot_destruct (_, e) as exn -> + Log.error + "Cannot load config file: %s - %s" + (Printexc.to_string exn) + (Printexc.to_string e) ; + raise exn + | e -> raise e let blocks_history = Clap.default_int -- GitLab From 6051729663748c311b3440642745f51403600f19 Mon Sep 17 00:00:00 2001 From: Guillaume Genestier Date: Fri, 25 Jul 2025 14:43:29 +0200 Subject: [PATCH 4/4] Tezt/Cloud: Scenario name in config file with consistency check --- tezt/lib_cloud/cli.ml | 6 ++--- tezt/lib_cloud/cli.mli | 3 ++- tezt/lib_cloud/tezt_cloud.mli | 4 ++-- tezt/tests/cloud/scenarios_cli.ml | 37 ++++++++++++++++++++++--------- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/tezt/lib_cloud/cli.ml b/tezt/lib_cloud/cli.ml index 1df128ad1953..945de1e91e85 100644 --- a/tezt/lib_cloud/cli.ml +++ b/tezt/lib_cloud/cli.ml @@ -51,7 +51,7 @@ type config = { log_rotation : int option; slack_channel_id : string option; slack_bot_token : string option; - scenario_specific : Data_encoding.Json.t option; + scenario_specific : (string * Data_encoding.Json.t) option; } let encoding = @@ -277,7 +277,7 @@ let encoding = (opt "slack_channel_id" string))) (obj2 (opt "slack_bot_token" string) - (opt "scenario_specific" Data_encoding.Json.encoding)))) + (opt "scenario_specific" (tup2 string Data_encoding.Json.encoding))))) let section = Clap.section @@ -306,7 +306,7 @@ let config = raise exn | e -> raise e) -let scenario_specific = Option.value ~default:(`O []) config.scenario_specific +let scenario_specific = config.scenario_specific let some = Option.some diff --git a/tezt/lib_cloud/cli.mli b/tezt/lib_cloud/cli.mli index d1292d628e62..55a88094e8e8 100644 --- a/tezt/lib_cloud/cli.mli +++ b/tezt/lib_cloud/cli.mli @@ -7,7 +7,8 @@ include module type of Tezt.Cli -val scenario_specific : Data_encoding.Json.t +(** The name and encoding of the scenario specific options if mentionned in the config file. *) +val scenario_specific : (string * Data_encoding.Json.t) option (** When [localhost] is [true], the cloud scenario should be run locally. This can be used to test a scenario before deploying it. *) diff --git a/tezt/lib_cloud/tezt_cloud.mli b/tezt/lib_cloud/tezt_cloud.mli index 3dbb16b2fb6f..b397424aad26 100644 --- a/tezt/lib_cloud/tezt_cloud.mli +++ b/tezt/lib_cloud/tezt_cloud.mli @@ -252,11 +252,11 @@ module Prometheus : sig val get_query_endpoint : query:string -> Uri.t option end +(** Expose the elements of [Cli] which are useful for the scenario. *) module Tezt_cloud_cli : sig - (** Equivalent to [Cli.prometheus] *) val prometheus : bool - val scenario_specific_json : Data_encoding.Json.t + val scenario_specific_json : (string * Data_encoding.Json.t) option end (** [register ~tags] register a set of jobs that can be used for setting diff --git a/tezt/tests/cloud/scenarios_cli.ml b/tezt/tests/cloud/scenarios_cli.ml index da1960ae8661..77e6a3f33401 100644 --- a/tezt/tests/cloud/scenarios_cli.ml +++ b/tezt/tests/cloud/scenarios_cli.ml @@ -89,6 +89,8 @@ let snapshot_typ : Snapshot_helpers.t Clap.typ = try Some (parse_snapshot (Some snapshot)) with _exn -> None) ~show:to_string +exception Scenario_mismatch + module type Dal = sig val blocks_history : int @@ -175,6 +177,8 @@ module type Dal = sig end module Dal () : Dal = struct + let scenario_name = "DAL" + let section = Clap.section ~description: @@ -182,18 +186,29 @@ module Dal () : Dal = struct "DAL" let config = - try - Data_encoding.Json.destruct - Scenarios_configuration.DAL.encoding - Tezt_cloud_cli.scenario_specific_json - with - | Json_encoding.Cannot_destruct (_, e) as exn -> + match Tezt_cloud_cli.scenario_specific_json with + | None -> + Data_encoding.Json.destruct Scenarios_configuration.DAL.encoding (`O []) + | Some (name, options) when name = scenario_name -> ( + try + Data_encoding.Json.destruct + Scenarios_configuration.DAL.encoding + options + with + | Json_encoding.Cannot_destruct (_, e) as exn -> + Log.error + "Cannot load config file: %s - %s" + (Printexc.to_string exn) + (Printexc.to_string e) ; + raise exn + | e -> raise e) + | Some (name, _options) -> Log.error - "Cannot load config file: %s - %s" - (Printexc.to_string exn) - (Printexc.to_string e) ; - raise exn - | e -> raise e + "Configuration file mismatch. This config file is for scenario %s \ + whereas the command was launched for scenario %s" + name + scenario_name ; + raise Scenario_mismatch let blocks_history = Clap.default_int -- GitLab