1#![allow(clippy::too_many_arguments)]
10
11use super::get_bin_path;
12use crate::{
13 add_services::config::PortRange,
14 local::{kill_network, run_network, LocalNetworkOptions},
15 print_banner, status_report, VerbosityLevel,
16};
17use color_eyre::{eyre::eyre, Help, Report, Result};
18use sn_evm::{EvmNetwork, RewardsAddress};
19use sn_logging::LogFormat;
20use sn_peers_acquisition::PeersArgs;
21use sn_releases::{ReleaseType, SafeReleaseRepoActions};
22use sn_service_management::{
23 control::ServiceController, get_local_node_registry_path, NodeRegistry,
24};
25use std::path::PathBuf;
26
27pub async fn join(
28 build: bool,
29 count: u16,
30 enable_metrics_server: bool,
31 _faucet_path: Option<PathBuf>,
32 _faucet_version: Option<String>,
33 interval: u64,
34 metrics_port: Option<PortRange>,
35 node_path: Option<PathBuf>,
36 node_port: Option<PortRange>,
37 node_version: Option<String>,
38 log_format: Option<LogFormat>,
39 owner: Option<String>,
40 owner_prefix: Option<String>,
41 peers_args: PeersArgs,
42 rpc_port: Option<PortRange>,
43 rewards_address: RewardsAddress,
44 evm_network: Option<EvmNetwork>,
45 skip_validation: bool,
46 verbosity: VerbosityLevel,
47) -> Result<(), Report> {
48 if verbosity != VerbosityLevel::Minimal {
49 print_banner("Joining Local Network");
50 }
51 info!("Joining local network");
52
53 if (enable_metrics_server || metrics_port.is_some()) && !cfg!(feature = "open-metrics") && build
54 {
55 return Err(eyre!(
56 "Metrics server is not available. Please enable the open-metrics feature flag. Run the command with the --features open-metrics"
57 ));
58 }
59
60 let local_node_reg_path = &get_local_node_registry_path()?;
61 let mut local_node_registry = NodeRegistry::load(local_node_reg_path)?;
62
63 let release_repo = <dyn SafeReleaseRepoActions>::default_config();
64
65 #[cfg(feature = "faucet")]
66 let faucet_bin_path = get_bin_path(
67 build,
68 _faucet_path,
69 ReleaseType::Faucet,
70 _faucet_version,
71 &*release_repo,
72 verbosity,
73 )
74 .await?;
75
76 let safenode_bin_path = get_bin_path(
77 build,
78 node_path,
79 ReleaseType::Safenode,
80 node_version,
81 &*release_repo,
82 verbosity,
83 )
84 .await?;
85
86 let peers = match peers_args.get_peers().await {
89 Ok(peers) => Some(peers),
90 Err(err) => match err {
91 sn_peers_acquisition::error::Error::PeersNotObtained => {
92 warn!("PeersNotObtained, peers is set to None");
93 None
94 }
95 _ => {
96 error!("Failed to obtain peers: {err:?}");
97 return Err(err.into());
98 }
99 },
100 };
101 let options = LocalNetworkOptions {
102 enable_metrics_server,
103 #[cfg(feature = "faucet")]
104 faucet_bin_path,
105 interval,
106 join: true,
107 metrics_port,
108 node_count: count,
109 node_port,
110 owner,
111 owner_prefix,
112 peers,
113 rpc_port,
114 safenode_bin_path,
115 skip_validation,
116 log_format,
117 rewards_address,
118 evm_network,
119 };
120 run_network(options, &mut local_node_registry, &ServiceController {}).await?;
121 Ok(())
122}
123
124pub fn kill(keep_directories: bool, verbosity: VerbosityLevel) -> Result<()> {
125 let local_reg_path = &get_local_node_registry_path()?;
126 let local_node_registry = NodeRegistry::load(local_reg_path)?;
127 if local_node_registry.nodes.is_empty() {
128 info!("No local network is currently running, cannot kill it");
129 println!("No local network is currently running");
130 } else {
131 if verbosity != VerbosityLevel::Minimal {
132 print_banner("Killing Local Network");
133 }
134 info!("Kill local network");
135 kill_network(&local_node_registry, keep_directories)?;
136 std::fs::remove_file(local_reg_path)?;
137 }
138 Ok(())
139}
140
141pub async fn run(
142 build: bool,
143 clean: bool,
144 count: u16,
145 enable_metrics_server: bool,
146 _faucet_path: Option<PathBuf>,
147 _faucet_version: Option<String>,
148 interval: u64,
149 metrics_port: Option<PortRange>,
150 node_path: Option<PathBuf>,
151 node_port: Option<PortRange>,
152 node_version: Option<String>,
153 log_format: Option<LogFormat>,
154 owner: Option<String>,
155 owner_prefix: Option<String>,
156 rpc_port: Option<PortRange>,
157 rewards_address: RewardsAddress,
158 evm_network: Option<EvmNetwork>,
159 skip_validation: bool,
160 verbosity: VerbosityLevel,
161) -> Result<(), Report> {
162 if (enable_metrics_server || metrics_port.is_some()) && !cfg!(feature = "open-metrics") && build
163 {
164 return Err(eyre!(
165 "Metrics server is not available. Please enable the open-metrics feature flag. Run the command with the --features open-metrics"
166 ));
167 }
168
169 let local_node_reg_path = &get_local_node_registry_path()?;
172 let mut local_node_registry: NodeRegistry = if clean {
173 debug!(
174 "Clean set to true, removing client, node dir, local registry and killing the network."
175 );
176 let client_data_path = dirs_next::data_dir()
177 .ok_or_else(|| eyre!("Could not obtain user's data directory"))?
178 .join("safe")
179 .join("client");
180 if client_data_path.is_dir() {
181 std::fs::remove_dir_all(client_data_path)?;
182 }
183 if local_node_reg_path.exists() {
184 std::fs::remove_file(local_node_reg_path)?;
185 }
186 kill(false, verbosity)?;
187 NodeRegistry::load(local_node_reg_path)?
188 } else {
189 let local_node_registry = NodeRegistry::load(local_node_reg_path)?;
190 if !local_node_registry.nodes.is_empty() {
191 error!("A local network is already running, cannot run a new one");
192 return Err(eyre!("A local network is already running")
193 .suggestion("Use the kill command to destroy the network then try again"));
194 }
195 local_node_registry
196 };
197
198 if verbosity != VerbosityLevel::Minimal {
199 print_banner("Launching Local Network");
200 }
201 info!("Launching local network");
202
203 let release_repo = <dyn SafeReleaseRepoActions>::default_config();
204
205 #[cfg(feature = "faucet")]
206 let faucet_bin_path = get_bin_path(
207 build,
208 _faucet_path,
209 ReleaseType::Faucet,
210 _faucet_version,
211 &*release_repo,
212 verbosity,
213 )
214 .await?;
215
216 let safenode_bin_path = get_bin_path(
217 build,
218 node_path,
219 ReleaseType::Safenode,
220 node_version,
221 &*release_repo,
222 verbosity,
223 )
224 .await?;
225
226 let options = LocalNetworkOptions {
227 enable_metrics_server,
228 #[cfg(feature = "faucet")]
229 faucet_bin_path,
230 join: false,
231 interval,
232 metrics_port,
233 node_port,
234 node_count: count,
235 owner,
236 owner_prefix,
237 peers: None,
238 rpc_port,
239 safenode_bin_path,
240 skip_validation,
241 log_format,
242 rewards_address,
243 evm_network,
244 };
245 run_network(options, &mut local_node_registry, &ServiceController {}).await?;
246
247 local_node_registry.save()?;
248 Ok(())
249}
250
251pub async fn status(details: bool, fail: bool, json: bool) -> Result<()> {
252 let mut local_node_registry = NodeRegistry::load(&get_local_node_registry_path()?)?;
253 if !json {
254 print_banner("Local Network");
255 }
256 status_report(
257 &mut local_node_registry,
258 &ServiceController {},
259 details,
260 json,
261 fail,
262 true,
263 )
264 .await?;
265 local_node_registry.save()?;
266 Ok(())
267}