diff --git a/CHANGES.rst b/CHANGES.rst index 44c163b53fe6c4d8551a69d8eab3f16119575cbe..05ca358ea48c06b0a3fef224901c3d1da01928fc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -40,6 +40,9 @@ Baker Agnostic Baker -------------- +- The agnostic baker now has the same CLI as the classical baker, getting rid of the + ``--`` separator. (MR :gl:`!17348`) + - The agnostic baker has a unified CLI such that incompatibilities between baking arguments for consecutive protocols can occur much harder, and will probably generate compilation errors. (MR :gl:`!16968`) diff --git a/src/bin_agnostic_baker/README.md b/src/bin_agnostic_baker/README.md index 16f828c25c309cace14499aa1fca3b2eb8b0dbf2..e279baf115f9d5855e359846121e6233cf8a82cd 100644 --- a/src/bin_agnostic_baker/README.md +++ b/src/bin_agnostic_baker/README.md @@ -19,19 +19,13 @@ used for real-life scenarios, for instance, baking on `mainnet`. ## Usage -To run the agnostic baker, the command line syntax is quite similar to the one +To run the agnostic baker, the command line syntax is similar to the one for the protocol-dependent baking binaries: ```bash -./octez-experimental-agnostic-baker [OCTEZ-EXPERIMENTAL-AGNOSTIC-BAKER-COMMANDS] \ --- [OCTEZ-BAKER-COMMANDS] +./octez-experimental-agnostic-baker [OCTEZ-BAKER-COMMANDS] ``` -The `[OCTEZ-EXPERIMENTAL-AGNOSTIC-BAKER-COMMANDS]` list consists of arguments specific -to the agnostic baker binary and they include: - --- `--help` : displays help information - The `[OCTEZ-BAKER-COMMANDS]` list consists of all the arguments that can be used for the specific protocol baking binary. To be more clear, if a user wants to use the agnostic baker to replace a baking command which would be @@ -43,8 +37,6 @@ the agnostic baker to replace a baking command which would be they can do this by using the same `[OCTEZ-BAKER-COMMANDS]` and let the agnostic baker run the baker process for ``, information obtained from the node. -Notice that the two types of arguments are separated by a clear `--`. - With the introduction of the agnostic baker, a unification of the CLI has also been achieved, therefore there will not be incompatibilities between two consecutive protocol baking commands. diff --git a/src/bin_agnostic_baker/main_agnostic_baker.ml b/src/bin_agnostic_baker/main_agnostic_baker.ml index 5dbaafca021b8bd12d26187dfc348f2cd5882d79..3cfa5ea7b1b677dd836b1556c35a699c462f2b9d 100644 --- a/src/bin_agnostic_baker/main_agnostic_baker.ml +++ b/src/bin_agnostic_baker/main_agnostic_baker.ml @@ -6,6 +6,15 @@ (* *) (*****************************************************************************) +(* Main entrypoint for the agnostic baker binary. + + We distinguish two cases: + 1. If the binary is called against a `--help` or `--version` command, then + there is no reason to connect to a node, find the current protocol etc. + 2. Otherwise, we run the agnostic baker daemon, which first obtains the + current protocol from the connected node, and then it monitors the chain + to determine when to switch to a new protocol baker process. *) + let[@warning "-32"] may_start_profiler baking_dir = match Tezos_profiler_unix.Profiler_instance.selected_backend () with | Some {instance_maker; _} -> @@ -13,15 +22,12 @@ let[@warning "-32"] may_start_profiler baking_dir = Agnostic_baker_profiler.init profiler_maker | None -> () -let run () = +let lwt_run ~args () = let open Lwt_result_syntax in - let Run_args.{node_endpoint; base_dir; baker_args} = - Run_args.parse_args Sys.argv - in let base_dir = Option.value ~default:Tezos_client_base_unix.Client_config.Cfg_file.default.base_dir - base_dir + (Run_args.get_base_dir args) in let*! () = Tezos_base_unix.Internal_event_unix.init @@ -29,15 +35,15 @@ let run () = () in () [@profiler.overwrite may_start_profiler base_dir] ; - let daemon = Daemon.create ~node_endpoint ~baker_args in + let daemon = Daemon.create ~node_endpoint:(Run_args.get_endpoint args) in let* (_ : unit) = Daemon.run daemon in let*! () = Lwt_utils.never_ending () in return_unit -let () = +let run ~args () = let open Lwt_result_syntax in let main_promise = - Lwt.catch run (function + Lwt.catch (lwt_run ~args) (function | Failure msg -> failwith "%s" msg | exn -> failwith "%s" (Printexc.to_string exn)) in @@ -55,3 +61,12 @@ let () = Format.pp_print_flush Format.std_formatter () ; let*! () = Tezos_base_unix.Internal_event_unix.close () in Lwt.return retcode)) + +let () = + let open Tezos_client_base_unix in + let args = Array.to_list Sys.argv in + if Run_args.(is_help_cmd args || is_version_cmd args || is_man_cmd args) then + Client_main_run.run + (module Daemon_config) + ~select_commands:(fun _ _ -> Lwt_result_syntax.return_nil) + else run ~args () diff --git a/src/lib_agnostic_baker/agnostic_baker_events.ml b/src/lib_agnostic_baker/agnostic_baker_events.ml index ce6a651baadc0269f83f0f0cbb7e746ba24d1af3..2440c018b0559cb9249425404adac1972be0dd8d 100644 --- a/src/lib_agnostic_baker/agnostic_baker_events.ml +++ b/src/lib_agnostic_baker/agnostic_baker_events.ml @@ -13,16 +13,14 @@ let alternative_color = Internal_event.Green (* Notice *) let starting_baker = - declare_2 + declare_1 ~section ~alternative_color ~level:Notice ~name:"starting_baker" - ~msg:"starting baker for protocol {proto} with arguments: {args}" + ~msg:"starting baker for protocol {proto}" ("proto", Protocol_hash.encoding) - ("args", string) ~pp1:Protocol_hash.pp_short - ~pp2:Format.pp_print_string let baker_running = declare_1 diff --git a/src/lib_agnostic_baker/daemon.ml b/src/lib_agnostic_baker/daemon.ml index 0dfe075731dce0c875b33a501ab1ca3b0997e3ac..c44da0537addb63101368757ce8af0618bc96c4d 100644 --- a/src/lib_agnostic_baker/daemon.ml +++ b/src/lib_agnostic_baker/daemon.ml @@ -25,14 +25,12 @@ type process = {thread : int Lwt.t; canceller : int Lwt.u} type baker = {protocol_hash : Protocol_hash.t; process : process} -(** [run_thread ~protocol_hash ~baker_commands ~baker_args ~cancel_promise ~logs_path] +(** [run_thread ~protocol_hash ~baker_commands ~cancel_promise ~logs_path] returns the main running thread for the baker given its protocol [~procol_hash], - corresponding commands [~baker_commands], with the command line arguments given by - [~baker_args] and Lwt cancellation promise [~cancel_promise]. + corresponding commands [~baker_commands] and Lwt cancellation promise [~cancel_promise]. The event logs are stored according to [~logs_path]. *) -let run_thread ~protocol_hash ~baker_commands ~baker_args ~cancel_promise - ~logs_path = +let run_thread ~protocol_hash ~baker_commands ~cancel_promise ~logs_path = let () = Client_commands.register protocol_hash @@ fun _network -> baker_commands in @@ -58,31 +56,16 @@ let run_thread ~protocol_hash ~baker_commands ~baker_args ~cancel_promise Client_main_run.lwt_run (module Config) ~select_commands - ~cmd_args:baker_args (* The underlying logging from the baker must not be initialised, otherwise we double log. *) ~disable_logging:true (); cancel_promise; ] -(** [spawn_baker protocol_hash ~baker_args] spawns a new baker process for the - given [protocol_hash] with command-line arguments [~baker_args]. *) -let spawn_baker protocol_hash ~baker_args = +(** [spawn_baker protocol_hash] spawns a new baker process for the given [protocol_hash]. *) +let spawn_baker protocol_hash = let open Lwt_result_syntax in - let args_as_string = - Format.asprintf - "%a" - (Format.pp_print_list - ~pp_sep:Format.pp_print_space - Format.pp_print_string) - baker_args - in - let*! () = - Agnostic_baker_events.(emit starting_baker) (protocol_hash, args_as_string) - in - (* Prepend a dummy binary argument required for command-line parsing. The argument - will be discarded, so its value is not important. *) - let baker_args = "./mock-binary" :: baker_args in + let*! () = Agnostic_baker_events.(emit starting_baker) protocol_hash in let cancel_promise, canceller = Lwt.wait () in let* thread = let*? plugin = @@ -95,7 +78,6 @@ let spawn_baker protocol_hash ~baker_args = @@ run_thread ~protocol_hash ~baker_commands - ~baker_args ~cancel_promise ~logs_path:Parameters.default_daily_logs_path in @@ -106,7 +88,6 @@ type baker_to_kill = {baker : baker; level_to_kill : int} type 'a state = { node_endpoint : string; - baker_args : string list; mutable current_baker : baker option; mutable old_baker : baker_to_kill option; } @@ -163,9 +144,7 @@ let hot_swap_baker ~state ~current_protocol_hash ~next_protocol_hash state.old_baker <- Some {baker = current_baker; level_to_kill = level_to_kill_old_baker} ; state.current_baker <- None ; - let* new_baker = - spawn_baker next_protocol_hash ~baker_args:state.baker_args - in + let* new_baker = spawn_baker next_protocol_hash in state.current_baker <- Some new_baker ; return_unit @@ -290,9 +269,7 @@ let may_start_initial_baker state = in match proto_status with | Active -> - let* current_baker = - spawn_baker protocol_hash ~baker_args:state.baker_args - in + let* current_baker = spawn_baker protocol_hash in state.current_baker <- Some current_baker ; return_unit | Frozen -> ( @@ -320,8 +297,8 @@ let may_start_initial_baker state = in may_start ~head_stream:None () -let create ~node_endpoint ~baker_args = - {node_endpoint; baker_args; current_baker = None; old_baker = None} +let create ~node_endpoint = + {node_endpoint; current_baker = None; old_baker = None} let run state = let open Lwt_result_syntax in diff --git a/src/lib_agnostic_baker/daemon.mli b/src/lib_agnostic_baker/daemon.mli index 38d8b90c5f336fbea181488d346d35772dbd1a44..618a7547cd7fc15643ae0d913cd61ca05a8da8e1 100644 --- a/src/lib_agnostic_baker/daemon.mli +++ b/src/lib_agnostic_baker/daemon.mli @@ -23,8 +23,8 @@ type 'a t -(** [create ~node_endpoint ~baker_args] returns a non initialized daemon. *) -val create : node_endpoint:string -> baker_args:string list -> 'a t +(** [create ~node_endpoint] returns a non initialized daemon. *) +val create : node_endpoint:string -> 'a t (** [run t] Runs the daemon responsible for the spawn/stop of the baker daemons. *) diff --git a/src/lib_agnostic_baker/run_args.ml b/src/lib_agnostic_baker/run_args.ml index 1ce213c7cedaddaf583faacf7c647b65cc00ee19..c9e53a8298319a257e38b0d2ea979f8c867333a8 100644 --- a/src/lib_agnostic_baker/run_args.ml +++ b/src/lib_agnostic_baker/run_args.ml @@ -6,48 +6,31 @@ (* *) (*****************************************************************************) -let endpoint_arg = "--endpoint" +(* Arguments for which we do not need to run a baker process. *) -let endpoint_short_arg = "-E" +let help_arg = "--help" -let base_dir_arg = "--base-dir" +let version_arg = "--version" -let base_dir_short_arg = "--b" +let man_arg = "man" -let help_arg = "--help" +let is_help_cmd = List.mem ~equal:String.equal help_arg -let print_help () = - Format.printf - "Usage:\n\ - \ octez-experimental-agnostic-baker \ - [OCTEZ-EXPERIMENTAL-AGNOSTIC-BAKER-COMMANDS] -- \ - [OCTEZ-BAKER-COMMANDS]@.@." ; - Format.printf - "OCTEZ-EXPERIMENTAL-AGNOSTIC-BAKER-COMMANDS:\n %s: display help@.@." - help_arg ; - Format.printf - "OCTEZ-BAKER-COMMANDS:\n Run ./octez-baker- --help@." +let is_version_cmd = List.mem ~equal:String.equal version_arg -let help_cmd args = - if List.mem ~equal:String.equal help_arg args then ( - print_help () ; - exit 0) - else () +let is_man_cmd = List.mem ~equal:String.equal man_arg -let version_cmd args = - if List.mem ~equal:String.equal "--version" args then ( - Format.printf "%s@." Tezos_version_value.Bin_version.octez_version_string ; - exit 0) - else () +(* Arguments needed for the start and monitoring of the agnostic baker process. *) -let split_args ?(on = "--") = - let rec loop acc = function - | [] -> (List.rev acc, []) - | hd :: tl when hd = on -> (List.rev acc, tl) - | hd :: tl -> loop (hd :: acc) tl - in - loop [] +let endpoint_arg = "--endpoint" + +let endpoint_short_arg = "-E" + +let base_dir_arg = "--base-dir" + +let base_dir_short_arg = "-d" +(** Retrieves the value for a given argument key. It checks both the long and short forms. *) let get_arg_value ~arg ?(short_arg = "") = let rec loop = function | [] -> None @@ -56,38 +39,8 @@ let get_arg_value ~arg ?(short_arg = "") = in loop -let get_endpoint = get_arg_value ~arg:endpoint_arg ~short_arg:endpoint_short_arg - -let fail_on_empty_baker_args baker_args = - if List.is_empty baker_args then ( - Format.eprintf - "Cannot run agnostic baker without any baker arguments. Please refer to \ - the following help:@." ; - print_help () ; - exit 1) +let get_endpoint args = + Option.value ~default:Parameters.default_node_endpoint + @@ get_arg_value ~arg:endpoint_arg ~short_arg:endpoint_short_arg args let get_base_dir = get_arg_value ~arg:base_dir_arg ~short_arg:base_dir_short_arg - -type args = { - node_endpoint : string; - base_dir : string option; - baker_args : string list; -} - -let parse_args all_args = - let all_args = Array.to_list all_args in - (* Specific vesrion case *) - let () = version_cmd all_args in - (* Remove the binary path *) - let all_args = Option.value ~default:[] (List.tl all_args) in - (* Split agnostic baker and baker arguments, that aims to be delimited by -- *) - let agnostic_baker_args, baker_args = split_args all_args in - let () = fail_on_empty_baker_args baker_args in - let () = help_cmd agnostic_baker_args in - let node_endpoint = - Option.value - ~default:Parameters.default_node_endpoint - (get_endpoint baker_args) - in - let base_dir = get_base_dir baker_args in - {node_endpoint; base_dir; baker_args} diff --git a/src/lib_agnostic_baker/run_args.mli b/src/lib_agnostic_baker/run_args.mli index 83a39f03a5f5ef16d292472cb939a0ea9efbd2d7..8483915b1e8592d7a9dd42ddcfbf398026fb6a9b 100644 --- a/src/lib_agnostic_baker/run_args.mli +++ b/src/lib_agnostic_baker/run_args.mli @@ -6,14 +6,19 @@ (* *) (*****************************************************************************) -(** Simple wrapper to handle the arguments of the agnostic baker. *) -type args = { - node_endpoint : string; - base_dir : string option; - baker_args : string list; -} +(** [is_help_cmd args] returns [true] iff [--help] is amongst [args]. *) +val is_help_cmd : string list -> bool -(** [parse_args args] is a raw utility that aims to parse the given - arguments from the command line and to return, respectively, the - [endpoint], [base_dir] and [baker_args]. *) -val parse_args : string array -> args +(** [is_version_cmd args] returns [true] iff [--version] is amongst [args]. *) +val is_version_cmd : string list -> bool + +(** [is_man_cmd args] returns [true] iff [man] is amongst [args]. *) +val is_man_cmd : string list -> bool + +(** [get_endpoint args] returns the value associated to the [--endpoint] argument + amongst [args], and in its absence using the default node RPC port. *) +val get_endpoint : string list -> string + +(** [get_base_dir] returns the value associated to the [--base-dir] argument + amonsgst [args]. *) +val get_base_dir : string list -> string option diff --git a/src/lib_client_base_unix/client_main_run.ml b/src/lib_client_base_unix/client_main_run.ml index 80b864f006996345271806fdcefdd3a3c44fad64..8a2542504370e46e3b01977818a23ad6f78c1710 100644 --- a/src/lib_client_base_unix/client_main_run.ml +++ b/src/lib_client_base_unix/client_main_run.ml @@ -418,8 +418,7 @@ let warn_if_argv0_name_not_octez () = executable_name (* Main (lwt) entry *) -let main (module C : M) ~select_commands ?cmd_args ?(disable_logging = false) () - = +let main (module C : M) ~select_commands ?(disable_logging = false) () = let open Lwt_result_syntax in let global_options = C.global_options () in let executable_name = Filename.basename Sys.executable_name in @@ -432,7 +431,7 @@ let main (module C : M) ~select_commands ?cmd_args ?(disable_logging = false) () | x :: rest -> move_autocomplete_token_upfront (x :: acc) rest | [] -> (List.rev acc, None) in - match Option.value ~default:(Array.to_list Sys.argv) cmd_args with + match Array.to_list Sys.argv with | _ :: args -> move_autocomplete_token_upfront [] args | [] -> ([], None) in @@ -657,8 +656,8 @@ let lwt_run (module M : M) ~(select_commands : RPC_client_unix.http_ctxt -> Client_config.cli_args -> - Client_context.full Tezos_clic.command list tzresult Lwt.t) ?cmd_args + Client_context.full Tezos_clic.command list tzresult Lwt.t) ?disable_logging () = Lwt.Exception_filter.(set handle_all_except_runtime) ; Lwt_exit.wrap_and_forward - @@ main (module M) ~select_commands ?cmd_args ?disable_logging () + @@ main (module M) ~select_commands ?disable_logging () diff --git a/src/lib_client_base_unix/client_main_run.mli b/src/lib_client_base_unix/client_main_run.mli index 3019d95eb51c468f23a81e127550f9547ceba78e..29028ef49d258f42229a50a745bdf064e918b3e9 100644 --- a/src/lib_client_base_unix/client_main_run.mli +++ b/src/lib_client_base_unix/client_main_run.mli @@ -103,17 +103,14 @@ val run : (** [lwt_run (module M) ~select_commands ?cmd_args ()] sets up the main application computation as an Lwt promise. Unlike [run], this function does not run the event loop, it merely returns the wrapped promise to be - integrated into an existing Lwt-based application. It can optionally use - [?cmd_args] as already parsed arguments to the [main] function. It can - also optionally disable logging of the underlying process via - [?disable_logging]. *) + integrated into an existing Lwt-based application. It can optionally + disable logging of the underlying process via [?disable_logging]. *) val lwt_run : (module M) -> select_commands: (RPC_client_unix.http_ctxt -> Client_config.cli_args -> Client_context.full Tezos_clic.command list tzresult Lwt.t) -> - ?cmd_args:string list -> ?disable_logging:bool -> unit -> int Lwt.t diff --git a/tezt/lib_tezos/agnostic_baker.ml b/tezt/lib_tezos/agnostic_baker.ml index 7255ce07c082cd179643189b65ea0b0c6bc7b841..8951de2bac1083e883e9cbd287d1265e3489a05c 100644 --- a/tezt/lib_tezos/agnostic_baker.ml +++ b/tezt/lib_tezos/agnostic_baker.ml @@ -230,7 +230,7 @@ let run ?env ?event_level ?event_sections_levels (agnostic_baker : t) = else ["with"; "local"; "node"; node_data_dir] in let arguments = - ["--"; "--endpoint"; node_addr; "--base-dir"; base_dir; "run"] + ["--endpoint"; node_addr; "--base-dir"; base_dir; "run"] @ run_args @ delegates @ liquidity_baking_toggle_vote @ votefile @ force_apply_from_round @ operations_pool @ dal_node_endpoint @ without_dal @ dal_node_timeout_percentage @ state_recorder @ node_version_check_bypass